Abstractions
The contracts and value objects every entity slice builds on.
Entity contract
interface IEntity {
get $id(): number | string
get $title(): string | undefined
}
abstract class EntityBase implements IEntity {
/* abstract $id, $title */
}Every model extends EntityBase and implements:
$id— the primary key. The service treatsnull,undefined,"new","", and any non-positive number (0, or the negative temp ids minted for new related-collection rows) as an unsaved instance and inserts it — so a barereturn this.idis safe; the convention isreturn this.id || "new". (The predicate is exported asisNewEntity($id).)$title— a human label used by selectors, breadcrumbs, and navigation.
EntityBase also exposes an entityType getter (= this.constructor.name) used internally as a cache key.
Search objects
interface ISearchObject extends Record<string, any> {
q?: string
archived?: ArchivedFilter
}
enum ArchivedFilter {
excluded = "excluded",
only = "only",
included = "included",
}
abstract class SearchObjectBase implements ISearchObject {
q?: string
}
class DefaultSearchObject extends SearchObjectBase {}q is the free-text search term. Add your own filter fields by extending SearchObjectBase. Every property becomes a query parameter (arrays → repeated keys); keys starting with $ are stripped before the request, so use them for client-only values.
archived selects the visibility of archived (soft-deleted) rows and is omitted when unset, leaving the server's default in charge. It is distinct from the entity's own isArchived property, which is the flag DELETE sets and a restore clears.
Paging & sorting
const DEFAULT_PAGESIZE = 10
interface IPagingInfo {
pageSize?: number
page?: number
}
class PagingInfo implements IPagingInfo {
/* page = 1, pageSize = DEFAULT_PAGESIZE */
}
interface ISortByInfo {
sortBy: string | Array<string>
}
class SortByInfo implements ISortByInfo {
/* sortBy: string | Array<string> = "" */
}Paging is applied automatically by the service: pageSize defaults to config.defaultPageSize, and page is omitted from the URL when ≤ 1. Pass pageSize: 0 to fetch all rows (capped by the server's MaxPageSize).
Result envelopes
The service returns these shapes (the client mirror of the API's wrapped responses):
type SearchResult<T> = { items: Array<T>; count: number; duration?: number }
type SaveResult<T> = { saved: T; isNew: boolean; affected?: number; duration?: number }Plus DetailsResult, ListResult, SavedResult, DeleteResult — see signatures. Bind save results to saved (not item); SaveResult and the raw server SavedResult differ.
Config
IConfig is the per-entity configuration object — covered in config.md.