用途:为 @data-client 定义 schema,用以描述端点返回的 JSON,并通过组合表达期望的数据结构,实现归一化缓存与一致的数据更新。
主要能力:对象类含 Entity(唯一对象去归一化)、EntityMixin(把既有类变为 Entity)、new Union(Entity)(多态对象 A|B)、{[key:string]: Schema}(不可变对象)、new Invalidate(Entity|Union)(删除实体)、new Lazy(() => Schema)(打破循环导入或延迟深层递归去归一化);列表类含 new Collection([Schema])(可变/可增长列表)、[Schema](不可变列表)、new All(Entity|Union)(列出某类全部实体);Map 类含 new Collection(Values(Schema)) 与 new Values(Schema);new Scalar({ lens, key, entity? }) 处理随运行时 lens(如组合、货币、地区)变化的实体字段;new Query(Queryable) 提供记忆化的编程式选择器,示例:const queryRemainingTodos = new Query(TodoResource.getList.schema, entries => entries.filter(todo => !todo.completed).length),Query 转换应定义在数据模型处(如 src/resources/),而非包在 useSuspense/useQuery 的自定义 Hook 内。
用法要点:Entity 子类需为所有非可选序列化字段定义默认值;仅当主键不等于 id 时重写 pk(),返回 number|string|undefined;可重写 Entity.process(value,parent,key,args) 依据 args/url 插入字段;可选 static schema 定义嵌套 schema 或反序列化函数。归一化流程:process() → pk() → validate() → 递归嵌套 schema → 若已存在则 mergeWithStore()(调用 shouldUpdate(),可能 shouldReorder()+merge()),元数据走 mergeMetaWithStore()。去归一化:createIfValid() → validate() → fromJS() → 递归 unvisit 嵌套 schema。Union 需配合鉴别字段,如 new Union({PullRequestEvent, IssuesEvent}, 'type')。Collection 的 pk 路由:嵌套在 Entity 中且可用时用 nestKey(parent,key),否则用 argsKey(...args);同时定义 argsKey 与 nestKey 可复用同一集合并共享状态。nonFilterArgumentKeys 默认排除以 'order' 开头的键,可传函数、RegExp 或 string[]。
限制与注意:归一化缓存存储的是可 JSON 序列化的普通对象(POJO),不是类实例;TS 裸字段类型不产生运行时默认值,需用 fromJS() 或赋默认值,否则 schema 推断失效;不要手动合并或“丰富”数据,改用 Entity.schema 做客户端 join;类型使用 rest/endpoint/graphql 的 Denormalize<> 而非 InstanceType<>。补充端点(元数据、统计、懒加载扩展)返回部分或异形数据时,使用同一 Entity 作为 schema,不要新建包装实体。具体价格与平台支持暂未提供。