Skip to main content

data-client-schema

Model data with @data-client schemas (Entity, EntityMixin, Collection, Union, Query, Values, All, Invalidate, Lazy, Scalar) for atomic, consistent, referentially-equal async data via normalization, identity-based caching, and a single source of truth. Use when defining or editing pk, static schema, resource()/RestEndpoint schema, mutable lists/maps (push/unshift/assign/remove/move), polymorphic/discriminated types, memoized selectors / derived data, partial/supplementary entities, relational/nested/joined data, optimistic updates, or cache invalidation across @data-client/rest, /endpoint, /graphql, or /normalizr. Apply proactively when discussing data models, remote data shape, caching, normalization, identity, joins, polymorphism, mutable collections, or store consistency.

Informations de source

Dépôt
reactive/data-client
Dernière activité de la source
19 août 2026 à 17:11
Langue détectée de SKILL.md
anglais
Étoiles
2 037
Forks
99

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Explorateur de fichiers
21 fichiers

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
data-client-schema
description
Model data with @data-client schemas (Entity, EntityMixin, Collection, Union, Query, Values, All, Invalidate, Lazy, Scalar) for atomic, consistent, referentially-equal async data via normalization, identity-based caching, and a single source of truth. Use when defining or editing pk, static schema, resource()/RestEndpoint schema, mutable lists/maps (push/unshift/assign/remove/move), polymorphic/discriminated types, memoized selectors / derived data, partial/supplementary entities, relational/nested/joined data, optimistic updates, or cache invalidation across @data-client/rest, /endpoint, /graphql, or /normalizr. Apply proactively when discussing data models, remote data shape, caching, normalization, identity, joins, polymorphism, mutable collections, or store consistency.
license
Apache 2.0
## 1. Defining Schemas Define [schemas](references/schema.md) to represent the JSON returned by an endpoint. Compose these to represent the data expected. ### Object - [Entity](references/Entity.md) - represents a single unique object (denormalized) - [EntityMixin](references/EntityMixin.md) - turn any pre-existing class into an Entity - [new Union(Entity)](references/Union.md) - polymorphic objects (A | B) - [`{[key:string]: Schema}`](references/Object.md) - immutable objects - [new Invalidate(Entity|Union)](references/Invalidate.md) - to delete an Entity - [new Lazy(() => Schema)](references/Lazy.md) - break circular imports / defer deep recursive denormalization ### List - [new Collection([Schema])](references/Collection.md) - mutable/growable lists - [`[Schema]`](references/Array.md) - immutable lists - [new All(Entity|Union)](references/All.md) - list all Entities of a kind ### Map - `new Collection(Values(Schema))` - mutable/growable maps - [new Values(Schema)](references/Values.md) - immutable maps ### Lens-dependent entity fields - [new Scalar({ lens, key, entity? })](references/Scalar.md) - fields that vary by runtime lens (portfolio, currency, locale) without entity mutation ### Derived / selector pattern - [new Query(Queryable)](references/Query.md) - memoized programmatic selectors ```ts const queryRemainingTodos = new Query( TodoResource.getList.schema, entries => entries.filter(todo => !todo.completed).length, ); ``` ```ts const groupTodoByUser = new Query( TodoResource.getList.schema, todos => Object.groupBy(todos, todo => todo.userId), ); ``` Define `Query` transformations with the data model (e.g. `src/resources/`) — not inside custom hooks wrapping useSuspense/useQuery, which hides data dependencies and couples data logic to view code. --- ## 2. Entity best practices - Every `Entity` subclass **defines defaults** for _all_ non-optional serialised fields. - Override `pk()` only when the primary key ≠ `id`. - `pk()` return type is `number | string | undefined` - Override `Entity.process(value, parent, key, args)` to insert fields based on args/url - `static schema` (optional) for nested schemas or deserialization functions - When designing APIs, prefer nesting entities --- ## 3. Entity lifecycle methods - **Normalize** (JSON response → cache): operates on POJOs; output is JSON-serializable plain data stored in the normalized cache. Order: `process()` → `pk()` → [validate()](references/validation.md) → **visit nested schemas** (recurse into `schema` fields) → if existing: `mergeWithStore()` which calls `shouldUpdate()` and maybe `shouldReorder()` + `merge()`; metadata via `mergeMetaWithStore()`. - **Denormalize** (cache → component): creates Entity **class instances** via `fromJS()`, restoring prototype chain so getters, methods, and `schema` processing work. Order: `createIfValid()` → [validate()](references/validation.md) → `fromJS()` → **unvisit nested schemas** (recurse into `schema` fields). --- ## 4. **Union Types (Polymorphic Schemas)** To define polymorphic resources (e.g., events), use [Union](references/Union.md) and a discriminator field. ```typescript import { Union } from '@data-client/rest'; // also available from @data-client/endpoint export abstract class Event extends Entity { type: EventType = 'Issue'; // discriminator field is shared /* ... */ } export class PullRequestEvent extends Event { /* ... */ } export class IssuesEvent extends Event { /* ... */ } export const EventResource = resource({ path: '/users/:login/events/public/:id', schema: new Union( { PullRequestEvent, IssuesEvent, // ...other event types... }, 'type', // discriminator field ), }); ``` --- ## 5. Collections (Mutable Lists & Maps) [Collections](references/Collection.md) wrap `Array` or `Values` schemas to enable mutations (add/remove/move). ### pk routing `pk()` uses `nestKey(parent, key)` when nested in an Entity and available; otherwise it uses `argsKey(...args)`, then serializes the result. Without options, it defaults to `argsKey: params => ({ ...params })`, using all endpoint args as the collection key. - `argsKey` — derive pk from endpoint arguments (default) - `nestKey` — derive pk from parent entity for nested shared-state collections Define **both** on the same `Collection` to reuse one definition top-level and nested. When `argsKey(args)` and `nestKey(parent)` produce the same object shape, the top-level fetch and the nested read resolve to the **same (referentially equal) array/map** — push/unshift/assign/move/remove on either updates both: ```ts const userTodos = new Collection([Todo], { argsKey: ({ userId }: { userId?: string }) => ({ userId }), nestKey: (parent: User) => ({ userId: parent.id }), }); ``` ### nonFilterArgumentKeys Default `createCollectionFilter` uses `nonFilterArgumentKeys` (default: keys starting with `'order'`) to exclude non-filter args when matching collections. This affects which existing collections receive new items from `push`/`unshift`/`assign`/`move`. Override as function, RegExp, or `string[]`: ```ts new Collection([Todo], { nonFilterArgumentKeys: /orderBy|sortDir/ }) ``` ### Extenders All usable with `ctrl.set()` (local-only) or via [RestEndpoint extenders](https://dataclient.io/rest/api/RestEndpoint) (network). | Method | Type | Description | |--------|------|-------------| | `push` | Array | Entity | Append items to end | | `unshift` | Array | Entity | Prepend items to start | | `assign` | Values | Merge entries into map | | `remove` | Both | Remove items by value from matching collections | | `move` | Both | Remove from collections matching existing state, add to collections matching new state | | `addWith(merge, filter?)` | Both | Custom creation schema (used internally by push/unshift/assign) | | `moveWith(merge)` | Both | Custom move schema (control insertion order, e.g., `unshift` merge for prepending) | --- ## 6. Supplementary Endpoints (enrich existing entities) When an endpoint returns partial or differently-shaped data for an entity already in cache (e.g., a metadata endpoint, a stats endpoint, a lazy-load expansion endpoint), use the **same Entity** as the schema — don't create a wrapper entity. See [partial-entities](references/partial-entities.md) for patterns and examples. --- ## 7. Best Practices & Notes - Always set up `schema` on every resource/entity/collection for normalization - Normalize deeply nested or relational data by defining proper schemas - Use `Entity.schema` for client-side joins - Use `Denormalize<>` type from rest/endpoint/graphql instead of InstanceType<>. This will handle all schemas like Unions, not just Entity. ## 8. Common Mistakes to Avoid - The normalized cache stores **plain JSON-serializable objects** (POJOs), not class instances. - Don't forget to use `fromJS()` or assign default properties for class fields — bare TS field types emit no runtime defaults, so schema inference breaks - Manually merging or 'enriching' data; instead use `Entity.schema` for client-side joins # References For detailed API documentation, see the [references](references/) directory: - [Entity](references/Entity.md) - Normalized data class - [EntityMixin](references/EntityMixin.md) - Turn any class into an Entity - [Collection](references/Collection.md) - Mutable/growable lists - [Union](references/Union.md) - Polymorphic schemas - [Query](references/Query.md) - Programmatic selectors - [Invalidate](references/Invalidate.md) - Delete entities - [Lazy](references/Lazy.md) - Deferred / circular schemas - [Scalar](references/Scalar.md) - Lens-dependent entity fields - [Scalar demo](references/_ScalarDemo.md) - [Values](references/Values.md) - Map schemas - [All](references/All.md) - List all entities of a kind - [Array](references/Array.md) - Immutable list schema - [Object](references/Object.md) - Object schema - [schema](references/schema.md) - Schema overview - [relational-data](references/relational-data.md) - Relational data guide - [computed-properties](references/computed-properties.md) - Computed properties guide - [partial-entities](references/partial-entities.md) - Partial entities guide - [side-effects](references/side-effects.md) - Side effects guide - [sorting-client-side](references/sorting-client-side.md) - Client-side sorting guide
Voir sur GitHub