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.

Datos de origen

Repositorio
reactive/data-client
Última actividad en el origen
19 de agosto de 2026 a las 17:11
Idioma detectado de SKILL.md
inglés
Estrellas
2037
Forks
99

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Explorador de archivos
21 archivos

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
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
Ver en GitHub