@dxos/echo 0.8.4-staging.ac66bdf99f → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (437) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +7 -7
  3. package/dist/lib/neutral/Annotation.mjs +37 -6
  4. package/dist/lib/neutral/Database.mjs +6 -17
  5. package/dist/lib/neutral/Entity.mjs +31 -20
  6. package/dist/lib/neutral/Err.mjs +3 -3
  7. package/dist/lib/neutral/Feed.mjs +23 -19
  8. package/dist/lib/neutral/Filter.mjs +13 -15
  9. package/dist/lib/neutral/Format.mjs +23 -3
  10. package/dist/lib/neutral/JsonSchema.mjs +7 -8
  11. package/dist/lib/neutral/Key.mjs +9 -5
  12. package/dist/lib/neutral/Migration.mjs +11 -10
  13. package/dist/lib/neutral/Obj.mjs +29 -20
  14. package/dist/lib/neutral/Order.mjs +7 -3
  15. package/dist/lib/neutral/Query.mjs +17 -17
  16. package/dist/lib/neutral/QueryResult.mjs +1 -1
  17. package/dist/lib/neutral/Ref.mjs +10 -9
  18. package/dist/lib/neutral/Registry.mjs +14 -0
  19. package/dist/lib/neutral/Relation.mjs +28 -25
  20. package/dist/lib/neutral/Scope.mjs +12 -0
  21. package/dist/lib/neutral/Tag.mjs +17 -14
  22. package/dist/lib/neutral/Type.mjs +54 -26
  23. package/dist/lib/neutral/{chunk-OMUPQMLR.mjs → chunk-35INCYOE.mjs} +1 -1
  24. package/dist/lib/neutral/chunk-35INCYOE.mjs.map +7 -0
  25. package/dist/lib/neutral/chunk-3PBP4V4O.mjs +101 -0
  26. package/dist/lib/neutral/chunk-3PBP4V4O.mjs.map +7 -0
  27. package/dist/lib/neutral/chunk-4ZUHOTCG.mjs +184 -0
  28. package/dist/lib/neutral/chunk-4ZUHOTCG.mjs.map +7 -0
  29. package/dist/lib/neutral/chunk-5SMDBFVB.mjs +108 -0
  30. package/dist/lib/neutral/chunk-5SMDBFVB.mjs.map +7 -0
  31. package/dist/lib/neutral/{chunk-OS35K56T.mjs → chunk-5SUJPHAE.mjs} +3 -3
  32. package/dist/lib/neutral/{chunk-OS35K56T.mjs.map → chunk-5SUJPHAE.mjs.map} +2 -2
  33. package/dist/lib/neutral/{chunk-GZQTCRJB.mjs → chunk-6M2Z6WBH.mjs} +22 -2
  34. package/dist/lib/neutral/chunk-6M2Z6WBH.mjs.map +7 -0
  35. package/dist/lib/neutral/{chunk-V36VO5SS.mjs → chunk-6YDI3J37.mjs} +32 -40
  36. package/dist/lib/neutral/chunk-6YDI3J37.mjs.map +7 -0
  37. package/dist/lib/neutral/{chunk-MOR5ERFM.mjs → chunk-7FPIAJIV.mjs} +701 -1256
  38. package/dist/lib/neutral/chunk-7FPIAJIV.mjs.map +7 -0
  39. package/dist/lib/neutral/{chunk-ANHVGJI4.mjs → chunk-7LOUAPYZ.mjs} +9 -5
  40. package/dist/lib/neutral/chunk-7LOUAPYZ.mjs.map +7 -0
  41. package/dist/lib/neutral/{chunk-JUXPFOEI.mjs → chunk-7PI7C4EF.mjs} +48 -88
  42. package/dist/lib/neutral/chunk-7PI7C4EF.mjs.map +7 -0
  43. package/dist/lib/neutral/{chunk-UBEZSGXY.mjs → chunk-BBFJWWAV.mjs} +6 -6
  44. package/dist/lib/neutral/chunk-BBFJWWAV.mjs.map +7 -0
  45. package/dist/lib/neutral/{chunk-UI6MWK5W.mjs → chunk-EVK6XBXO.mjs} +16 -2
  46. package/dist/lib/neutral/chunk-EVK6XBXO.mjs.map +7 -0
  47. package/dist/lib/neutral/{chunk-7RO7CPBZ.mjs → chunk-IGK6FN65.mjs} +2 -2
  48. package/dist/lib/neutral/{chunk-HBUZJNZO.mjs → chunk-LWXVKPPW.mjs} +94 -99
  49. package/dist/lib/neutral/chunk-LWXVKPPW.mjs.map +7 -0
  50. package/dist/lib/neutral/{chunk-BVOFLCVF.mjs → chunk-MZ7K3MLL.mjs} +9 -6
  51. package/dist/lib/neutral/chunk-MZ7K3MLL.mjs.map +7 -0
  52. package/dist/lib/neutral/{chunk-TBKX6JQO.mjs → chunk-O6BH7EPN.mjs} +30 -3
  53. package/dist/lib/neutral/chunk-O6BH7EPN.mjs.map +7 -0
  54. package/dist/lib/neutral/{chunk-EAMSSLZC.mjs → chunk-QQIYS74I.mjs} +83 -46
  55. package/dist/lib/neutral/chunk-QQIYS74I.mjs.map +7 -0
  56. package/dist/lib/neutral/chunk-R5W6DXR4.mjs +678 -0
  57. package/dist/lib/neutral/chunk-R5W6DXR4.mjs.map +7 -0
  58. package/dist/lib/neutral/{chunk-WAK4DMFV.mjs → chunk-RIVWNMSF.mjs} +12 -7
  59. package/dist/lib/neutral/chunk-RIVWNMSF.mjs.map +7 -0
  60. package/dist/lib/neutral/{chunk-T6W2LEZU.mjs → chunk-SBVFRTST.mjs} +73 -38
  61. package/dist/lib/neutral/chunk-SBVFRTST.mjs.map +7 -0
  62. package/dist/lib/neutral/chunk-T6E37YIP.mjs +251 -0
  63. package/dist/lib/neutral/chunk-T6E37YIP.mjs.map +7 -0
  64. package/dist/lib/neutral/{chunk-DQYLD2RB.mjs → chunk-TFEWTY5A.mjs} +155 -129
  65. package/dist/lib/neutral/chunk-TFEWTY5A.mjs.map +7 -0
  66. package/dist/lib/neutral/{chunk-B4BASU6W.mjs → chunk-TYGKCRMK.mjs} +85 -76
  67. package/dist/lib/neutral/chunk-TYGKCRMK.mjs.map +7 -0
  68. package/dist/lib/neutral/{chunk-4OIBYSXE.mjs → chunk-UUP46KUQ.mjs} +78 -32
  69. package/dist/lib/neutral/chunk-UUP46KUQ.mjs.map +7 -0
  70. package/dist/lib/neutral/chunk-WISOH2XH.mjs +36 -0
  71. package/dist/lib/neutral/chunk-WISOH2XH.mjs.map +7 -0
  72. package/dist/lib/neutral/{chunk-G3IQMKF7.mjs → chunk-WTQJHC75.mjs} +111 -112
  73. package/dist/lib/neutral/chunk-WTQJHC75.mjs.map +7 -0
  74. package/dist/lib/neutral/chunk-WU3GIANS.mjs +31 -0
  75. package/dist/lib/neutral/chunk-WU3GIANS.mjs.map +7 -0
  76. package/dist/lib/neutral/{chunk-TU3GW67D.mjs → chunk-ZGNNFYHS.mjs} +40 -40
  77. package/dist/lib/neutral/chunk-ZGNNFYHS.mjs.map +7 -0
  78. package/dist/lib/neutral/index.mjs +47 -41
  79. package/dist/lib/neutral/internal/index.mjs +137 -72
  80. package/dist/lib/neutral/meta.json +1 -1
  81. package/dist/lib/neutral/testing/index.mjs +261 -178
  82. package/dist/lib/neutral/testing/index.mjs.map +4 -4
  83. package/dist/types/src/Annotation.d.ts +108 -4
  84. package/dist/types/src/Annotation.d.ts.map +1 -1
  85. package/dist/types/src/Annotation.test.d.ts +2 -0
  86. package/dist/types/src/Annotation.test.d.ts.map +1 -0
  87. package/dist/types/src/Collection.d.ts +2 -3
  88. package/dist/types/src/Collection.d.ts.map +1 -1
  89. package/dist/types/src/Database.d.ts +56 -49
  90. package/dist/types/src/Database.d.ts.map +1 -1
  91. package/dist/types/src/Dataset.d.ts +16 -6
  92. package/dist/types/src/Dataset.d.ts.map +1 -1
  93. package/dist/types/src/Entity.d.ts +101 -28
  94. package/dist/types/src/Entity.d.ts.map +1 -1
  95. package/dist/types/src/Err.d.ts +27 -27
  96. package/dist/types/src/Err.d.ts.map +1 -1
  97. package/dist/types/src/Feed.d.ts +66 -19
  98. package/dist/types/src/Feed.d.ts.map +1 -1
  99. package/dist/types/src/Filter.d.ts +38 -12
  100. package/dist/types/src/Filter.d.ts.map +1 -1
  101. package/dist/types/src/Format.d.ts +0 -2
  102. package/dist/types/src/Format.d.ts.map +1 -1
  103. package/dist/types/src/Hypergraph.d.ts +14 -9
  104. package/dist/types/src/Hypergraph.d.ts.map +1 -1
  105. package/dist/types/src/Json.d.ts +33 -0
  106. package/dist/types/src/Json.d.ts.map +1 -0
  107. package/dist/types/src/Json.test.d.ts +2 -0
  108. package/dist/types/src/Json.test.d.ts.map +1 -0
  109. package/dist/types/src/JsonSchema.d.ts +2 -2
  110. package/dist/types/src/JsonSchema.d.ts.map +1 -1
  111. package/dist/types/src/Key.d.ts +1 -1
  112. package/dist/types/src/Key.d.ts.map +1 -1
  113. package/dist/types/src/Migration.d.ts +26 -11
  114. package/dist/types/src/Migration.d.ts.map +1 -1
  115. package/dist/types/src/Obj.d.ts +104 -61
  116. package/dist/types/src/Obj.d.ts.map +1 -1
  117. package/dist/types/src/Order.d.ts +10 -0
  118. package/dist/types/src/Order.d.ts.map +1 -1
  119. package/dist/types/src/Query.d.ts +34 -12
  120. package/dist/types/src/Query.d.ts.map +1 -1
  121. package/dist/types/src/QueryResult.d.ts +21 -0
  122. package/dist/types/src/QueryResult.d.ts.map +1 -1
  123. package/dist/types/src/Ref.d.ts +15 -7
  124. package/dist/types/src/Ref.d.ts.map +1 -1
  125. package/dist/types/src/Registry.d.ts +131 -0
  126. package/dist/types/src/Registry.d.ts.map +1 -0
  127. package/dist/types/src/Relation.d.ts +73 -41
  128. package/dist/types/src/Relation.d.ts.map +1 -1
  129. package/dist/types/src/Scope.d.ts +35 -0
  130. package/dist/types/src/Scope.d.ts.map +1 -0
  131. package/dist/types/src/Tag.d.ts +21 -5
  132. package/dist/types/src/Tag.d.ts.map +1 -1
  133. package/dist/types/src/Type.d.ts +362 -95
  134. package/dist/types/src/Type.d.ts.map +1 -1
  135. package/dist/types/src/View.d.ts +9 -12
  136. package/dist/types/src/View.d.ts.map +1 -1
  137. package/dist/types/src/exemplars.test.d.ts +2 -0
  138. package/dist/types/src/exemplars.test.d.ts.map +1 -0
  139. package/dist/types/src/index.d.ts +4 -3
  140. package/dist/types/src/index.d.ts.map +1 -1
  141. package/dist/types/src/internal/Annotation/annotations.d.ts +79 -38
  142. package/dist/types/src/internal/Annotation/annotations.d.ts.map +1 -1
  143. package/dist/types/src/internal/Annotation/dictionary.d.ts +24 -0
  144. package/dist/types/src/internal/Annotation/dictionary.d.ts.map +1 -0
  145. package/dist/types/src/internal/Annotation/entity-dictionary.d.ts +14 -0
  146. package/dist/types/src/internal/Annotation/entity-dictionary.d.ts.map +1 -0
  147. package/dist/types/src/internal/Annotation/index.d.ts +4 -2
  148. package/dist/types/src/internal/Annotation/index.d.ts.map +1 -1
  149. package/dist/types/src/internal/Annotation/sorting.d.ts.map +1 -1
  150. package/dist/types/src/internal/Annotation/util.d.ts +14 -5
  151. package/dist/types/src/internal/Annotation/util.d.ts.map +1 -1
  152. package/dist/types/src/internal/Entity/api.d.ts +17 -3
  153. package/dist/types/src/internal/Entity/api.d.ts.map +1 -1
  154. package/dist/types/src/internal/Entity/entity.d.ts +72 -8
  155. package/dist/types/src/internal/Entity/entity.d.ts.map +1 -1
  156. package/dist/types/src/internal/Entity/guard.d.ts +10 -0
  157. package/dist/types/src/internal/Entity/guard.d.ts.map +1 -0
  158. package/dist/types/src/internal/Entity/index.d.ts +2 -0
  159. package/dist/types/src/internal/Entity/index.d.ts.map +1 -1
  160. package/dist/types/src/internal/Entity/model.d.ts +21 -17
  161. package/dist/types/src/internal/Entity/model.d.ts.map +1 -1
  162. package/dist/types/src/internal/Entity/object.d.ts +3 -3
  163. package/dist/types/src/internal/Entity/object.d.ts.map +1 -1
  164. package/dist/types/src/internal/Entity/relation.d.ts +30 -7
  165. package/dist/types/src/internal/Entity/relation.d.ts.map +1 -1
  166. package/dist/types/src/internal/Entity/type-kind.d.ts +24 -0
  167. package/dist/types/src/internal/Entity/type-kind.d.ts.map +1 -0
  168. package/dist/types/src/internal/Entity/type-uri.d.ts +24 -0
  169. package/dist/types/src/internal/Entity/type-uri.d.ts.map +1 -0
  170. package/dist/types/src/internal/Entity/version.d.ts.map +1 -1
  171. package/dist/types/src/internal/Format/date.d.ts.map +1 -1
  172. package/dist/types/src/internal/Format/format.d.ts +3 -2
  173. package/dist/types/src/internal/Format/format.d.ts.map +1 -1
  174. package/dist/types/src/internal/Format/index.d.ts +2 -2
  175. package/dist/types/src/internal/Format/index.d.ts.map +1 -1
  176. package/dist/types/src/internal/Format/number.d.ts.map +1 -1
  177. package/dist/types/src/internal/Format/object.d.ts +3 -1
  178. package/dist/types/src/internal/Format/object.d.ts.map +1 -1
  179. package/dist/types/src/internal/Format/types.d.ts.map +1 -1
  180. package/dist/types/src/internal/JsonSchema/json-schema-normalize.d.ts.map +1 -1
  181. package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts +34 -34
  182. package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts.map +1 -1
  183. package/dist/types/src/internal/JsonSchema/json-schema.d.ts +3 -2
  184. package/dist/types/src/internal/JsonSchema/json-schema.d.ts.map +1 -1
  185. package/dist/types/src/internal/Obj/atoms.d.ts +38 -0
  186. package/dist/types/src/internal/Obj/atoms.d.ts.map +1 -0
  187. package/dist/types/src/internal/Obj/clone.d.ts.map +1 -1
  188. package/dist/types/src/internal/Obj/common.d.ts.map +1 -1
  189. package/dist/types/src/internal/Obj/create-object.d.ts +12 -12
  190. package/dist/types/src/internal/Obj/create-object.d.ts.map +1 -1
  191. package/dist/types/src/internal/Obj/deleted.d.ts.map +1 -1
  192. package/dist/types/src/internal/Obj/index.d.ts +1 -1
  193. package/dist/types/src/internal/Obj/index.d.ts.map +1 -1
  194. package/dist/types/src/internal/Obj/json-serializer.d.ts +8 -8
  195. package/dist/types/src/internal/Obj/json-serializer.d.ts.map +1 -1
  196. package/dist/types/src/internal/Obj/set-value.d.ts +1 -1
  197. package/dist/types/src/internal/Obj/set-value.d.ts.map +1 -1
  198. package/dist/types/src/internal/Obj/snapshot.d.ts.map +1 -1
  199. package/dist/types/src/internal/Obj/typed-object.d.ts +1 -1
  200. package/dist/types/src/internal/Query/index.d.ts +2 -0
  201. package/dist/types/src/internal/Query/index.d.ts.map +1 -0
  202. package/dist/types/src/internal/{Query.d.ts → Query/pretty.d.ts} +1 -1
  203. package/dist/types/src/internal/Query/pretty.d.ts.map +1 -0
  204. package/dist/types/src/internal/Ref/atoms.d.ts +10 -0
  205. package/dist/types/src/internal/Ref/atoms.d.ts.map +1 -0
  206. package/dist/types/src/internal/Ref/ref-array.d.ts +2 -2
  207. package/dist/types/src/internal/Ref/ref.d.ts +50 -19
  208. package/dist/types/src/internal/Ref/ref.d.ts.map +1 -1
  209. package/dist/types/src/internal/Ref/utils.d.ts +8 -0
  210. package/dist/types/src/internal/Ref/utils.d.ts.map +1 -0
  211. package/dist/types/src/internal/Type/compose.d.ts.map +1 -1
  212. package/dist/types/src/internal/Type/index.d.ts +1 -2
  213. package/dist/types/src/internal/Type/index.d.ts.map +1 -1
  214. package/dist/types/src/internal/Type/manipulation.d.ts +0 -1
  215. package/dist/types/src/internal/Type/manipulation.d.ts.map +1 -1
  216. package/dist/types/src/internal/Type/type-schema.d.ts +52 -0
  217. package/dist/types/src/internal/Type/type-schema.d.ts.map +1 -0
  218. package/dist/types/src/internal/common/api/meta.d.ts +14 -11
  219. package/dist/types/src/internal/common/api/meta.d.ts.map +1 -1
  220. package/dist/types/src/internal/common/proxy/change-context.d.ts +1 -1
  221. package/dist/types/src/internal/common/proxy/change-context.d.ts.map +1 -1
  222. package/dist/types/src/internal/common/proxy/define-hidden-property.d.ts.map +1 -1
  223. package/dist/types/src/internal/common/proxy/errors.d.ts +1 -1
  224. package/dist/types/src/internal/common/proxy/errors.d.ts.map +1 -1
  225. package/dist/types/src/internal/common/proxy/event-batch.d.ts.map +1 -1
  226. package/dist/types/src/internal/common/proxy/json-serializer.d.ts.map +1 -1
  227. package/dist/types/src/internal/common/proxy/make-object.d.ts +11 -5
  228. package/dist/types/src/internal/common/proxy/make-object.d.ts.map +1 -1
  229. package/dist/types/src/internal/common/proxy/ownership.d.ts.map +1 -1
  230. package/dist/types/src/internal/common/proxy/proxy-utils.d.ts.map +1 -1
  231. package/dist/types/src/internal/common/proxy/reactive-array.d.ts +1 -1
  232. package/dist/types/src/internal/common/proxy/reactive.d.ts +1 -1
  233. package/dist/types/src/internal/common/proxy/reactive.d.ts.map +1 -1
  234. package/dist/types/src/internal/common/proxy/reactive.test.d.ts +2 -0
  235. package/dist/types/src/internal/common/proxy/reactive.test.d.ts.map +1 -0
  236. package/dist/types/src/internal/common/proxy/schema-validator.d.ts.map +1 -1
  237. package/dist/types/src/internal/common/proxy/typed-handler.d.ts +18 -2
  238. package/dist/types/src/internal/common/proxy/typed-handler.d.ts.map +1 -1
  239. package/dist/types/src/internal/common/types/base.d.ts +4 -4
  240. package/dist/types/src/internal/common/types/base.d.ts.map +1 -1
  241. package/dist/types/src/internal/common/types/entity.d.ts +62 -5
  242. package/dist/types/src/internal/common/types/entity.d.ts.map +1 -1
  243. package/dist/types/src/internal/common/types/index.d.ts +1 -1
  244. package/dist/types/src/internal/common/types/index.d.ts.map +1 -1
  245. package/dist/types/src/internal/common/types/meta.d.ts +33 -12
  246. package/dist/types/src/internal/common/types/meta.d.ts.map +1 -1
  247. package/dist/types/src/internal/common/types/model-symbols.d.ts +15 -4
  248. package/dist/types/src/internal/common/types/model-symbols.d.ts.map +1 -1
  249. package/dist/types/src/internal/common/types/typename.d.ts +7 -0
  250. package/dist/types/src/internal/common/types/typename.d.ts.map +1 -1
  251. package/dist/types/src/internal/common/types/version.d.ts +1 -1
  252. package/dist/types/src/internal/common/types/well-known-types.d.ts +11 -0
  253. package/dist/types/src/internal/common/types/well-known-types.d.ts.map +1 -0
  254. package/dist/types/src/internal/index.d.ts +2 -2
  255. package/dist/types/src/internal/index.d.ts.map +1 -1
  256. package/dist/types/src/testing/index.d.ts +1 -0
  257. package/dist/types/src/testing/index.d.ts.map +1 -1
  258. package/dist/types/src/testing/registry.d.ts +9 -0
  259. package/dist/types/src/testing/registry.d.ts.map +1 -0
  260. package/dist/types/src/testing/test-data.d.ts +8 -8
  261. package/dist/types/src/testing/test-data.d.ts.map +1 -1
  262. package/dist/types/src/testing/test-schema.d.ts +83 -89
  263. package/dist/types/src/testing/test-schema.d.ts.map +1 -1
  264. package/dist/types/src/testing/util.d.ts +5 -3
  265. package/dist/types/src/testing/util.d.ts.map +1 -1
  266. package/dist/types/tsconfig.tsbuildinfo +1 -1
  267. package/package.json +26 -24
  268. package/src/Annotation.test.ts +439 -0
  269. package/src/Annotation.ts +158 -4
  270. package/src/Collection.ts +5 -9
  271. package/src/Database.ts +93 -100
  272. package/src/Dataset.ts +10 -2
  273. package/src/Entity.test.ts +116 -6
  274. package/src/Entity.ts +134 -32
  275. package/src/Err.ts +4 -4
  276. package/src/Feed.ts +92 -44
  277. package/src/Filter.ts +70 -40
  278. package/src/Format.ts +0 -4
  279. package/src/Hypergraph.ts +14 -9
  280. package/src/Json.test.ts +175 -0
  281. package/src/Json.ts +103 -0
  282. package/src/Key.ts +1 -1
  283. package/src/Migration.ts +39 -19
  284. package/src/Obj.test.ts +122 -20
  285. package/src/Obj.ts +168 -91
  286. package/src/Order.ts +22 -0
  287. package/src/Query.test.ts +183 -154
  288. package/src/Query.ts +172 -85
  289. package/src/QueryResult.ts +26 -0
  290. package/src/Ref.ts +22 -4
  291. package/src/Registry.ts +155 -0
  292. package/src/Relation.test.ts +10 -10
  293. package/src/Relation.ts +116 -69
  294. package/src/Scope.ts +50 -0
  295. package/src/Tag.md +88 -0
  296. package/src/Tag.ts +49 -6
  297. package/src/Type.test.ts +223 -18
  298. package/src/Type.ts +609 -131
  299. package/src/View.ts +14 -23
  300. package/src/exemplars.test.ts +21 -0
  301. package/src/index.ts +4 -4
  302. package/src/internal/Annotation/annotations.test.ts +31 -11
  303. package/src/internal/Annotation/annotations.ts +143 -111
  304. package/src/internal/Annotation/dictionary.ts +47 -0
  305. package/src/internal/Annotation/entity-dictionary.ts +74 -0
  306. package/src/internal/Annotation/index.ts +4 -2
  307. package/src/internal/Annotation/util.ts +17 -8
  308. package/src/internal/Entity/api.ts +54 -7
  309. package/src/internal/Entity/entity.ts +196 -47
  310. package/src/internal/Entity/guard.ts +26 -0
  311. package/src/internal/Entity/index.ts +2 -0
  312. package/src/internal/Entity/model.ts +38 -28
  313. package/src/internal/Entity/object.ts +21 -5
  314. package/src/internal/Entity/relation.ts +68 -34
  315. package/src/internal/Entity/type-kind.ts +75 -0
  316. package/src/internal/Entity/type-uri.ts +92 -0
  317. package/src/internal/Entity/util.ts +9 -9
  318. package/src/internal/Format/date.ts +0 -4
  319. package/src/internal/Format/format.test.ts +21 -0
  320. package/src/internal/Format/index.ts +2 -3
  321. package/src/internal/Format/object.ts +21 -4
  322. package/src/internal/Format/types.ts +1 -1
  323. package/src/internal/JsonSchema/annotations.ts +1 -1
  324. package/src/internal/JsonSchema/json-schema-type.ts +4 -4
  325. package/src/internal/JsonSchema/json-schema.test.ts +71 -145
  326. package/src/internal/JsonSchema/json-schema.ts +49 -35
  327. package/src/internal/Obj/atoms.ts +244 -0
  328. package/src/internal/Obj/clone.ts +9 -4
  329. package/src/internal/Obj/create-object.test.ts +12 -10
  330. package/src/internal/Obj/create-object.ts +68 -22
  331. package/src/internal/Obj/index.ts +1 -1
  332. package/src/internal/Obj/inspect.ts +5 -3
  333. package/src/internal/Obj/json-serializer.test.ts +101 -22
  334. package/src/internal/Obj/json-serializer.ts +89 -33
  335. package/src/internal/Obj/set-value.test.ts +22 -45
  336. package/src/internal/Obj/set-value.ts +12 -19
  337. package/src/internal/Obj/snapshot.ts +13 -4
  338. package/src/internal/Obj/typed-object.test.ts +9 -11
  339. package/src/internal/Obj/typed-object.ts +1 -1
  340. package/src/internal/Query/index.ts +5 -0
  341. package/src/internal/{Query.ts → Query/pretty.ts} +40 -12
  342. package/src/internal/Ref/atoms.ts +20 -0
  343. package/src/internal/Ref/ref-array.ts +3 -3
  344. package/src/internal/Ref/ref.test.ts +18 -27
  345. package/src/internal/Ref/ref.ts +137 -59
  346. package/src/internal/Ref/utils.ts +45 -0
  347. package/src/internal/Type/compose.test.ts +3 -1
  348. package/src/internal/Type/index.ts +1 -2
  349. package/src/internal/Type/manipulation.ts +0 -25
  350. package/src/internal/Type/type-schema.ts +60 -0
  351. package/src/internal/common/README.md +2 -2
  352. package/src/internal/common/api/meta.ts +19 -17
  353. package/src/internal/common/proxy/change-context.ts +1 -1
  354. package/src/internal/common/proxy/change.test.ts +91 -83
  355. package/src/internal/common/proxy/errors.ts +2 -2
  356. package/src/internal/common/proxy/handler.test.ts +1 -1
  357. package/src/internal/common/proxy/json-serializer.ts +27 -16
  358. package/src/internal/common/proxy/make-object.ts +44 -20
  359. package/src/internal/common/proxy/ownership.ts +2 -2
  360. package/src/internal/common/proxy/reactive-array.ts +1 -1
  361. package/src/internal/common/proxy/reactive.test.ts +54 -0
  362. package/src/internal/common/proxy/reactive.ts +11 -2
  363. package/src/internal/common/proxy/schema.test.ts +48 -86
  364. package/src/internal/common/proxy/typed-handler.test.ts +12 -11
  365. package/src/internal/common/proxy/typed-handler.ts +78 -16
  366. package/src/internal/common/proxy/typed-object.test.ts +16 -28
  367. package/src/internal/common/types/base.ts +4 -4
  368. package/src/internal/common/types/entity.ts +80 -1
  369. package/src/internal/common/types/index.ts +6 -1
  370. package/src/internal/common/types/meta.ts +62 -20
  371. package/src/internal/common/types/model-symbols.ts +24 -4
  372. package/src/internal/common/types/typename.ts +39 -3
  373. package/src/internal/common/types/well-known-types.ts +15 -0
  374. package/src/internal/index.ts +6 -4
  375. package/src/testing/api.test.ts +15 -9
  376. package/src/testing/index.ts +1 -0
  377. package/src/testing/registry.ts +44 -0
  378. package/src/testing/test-data.ts +159 -99
  379. package/src/testing/test-schema.ts +22 -58
  380. package/src/testing/util.ts +14 -11
  381. package/dist/lib/neutral/Extension.mjs +0 -18
  382. package/dist/lib/neutral/SchemaRegistry.mjs +0 -2
  383. package/dist/lib/neutral/chunk-2KHZ36F5.mjs +0 -361
  384. package/dist/lib/neutral/chunk-2KHZ36F5.mjs.map +0 -7
  385. package/dist/lib/neutral/chunk-4OIBYSXE.mjs.map +0 -7
  386. package/dist/lib/neutral/chunk-4P3IXBLT.mjs +0 -45
  387. package/dist/lib/neutral/chunk-4P3IXBLT.mjs.map +0 -7
  388. package/dist/lib/neutral/chunk-ANHVGJI4.mjs.map +0 -7
  389. package/dist/lib/neutral/chunk-B4BASU6W.mjs.map +0 -7
  390. package/dist/lib/neutral/chunk-BNCCGLJN.mjs +0 -7
  391. package/dist/lib/neutral/chunk-BNCCGLJN.mjs.map +0 -7
  392. package/dist/lib/neutral/chunk-BVOFLCVF.mjs.map +0 -7
  393. package/dist/lib/neutral/chunk-DQYLD2RB.mjs.map +0 -7
  394. package/dist/lib/neutral/chunk-EAMSSLZC.mjs.map +0 -7
  395. package/dist/lib/neutral/chunk-G3IQMKF7.mjs.map +0 -7
  396. package/dist/lib/neutral/chunk-GZQTCRJB.mjs.map +0 -7
  397. package/dist/lib/neutral/chunk-HBUZJNZO.mjs.map +0 -7
  398. package/dist/lib/neutral/chunk-JUXPFOEI.mjs.map +0 -7
  399. package/dist/lib/neutral/chunk-MOR5ERFM.mjs.map +0 -7
  400. package/dist/lib/neutral/chunk-OMUPQMLR.mjs.map +0 -7
  401. package/dist/lib/neutral/chunk-PHU22NLC.mjs +0 -136
  402. package/dist/lib/neutral/chunk-PHU22NLC.mjs.map +0 -7
  403. package/dist/lib/neutral/chunk-ROG4RXXL.mjs +0 -97
  404. package/dist/lib/neutral/chunk-ROG4RXXL.mjs.map +0 -7
  405. package/dist/lib/neutral/chunk-T6W2LEZU.mjs.map +0 -7
  406. package/dist/lib/neutral/chunk-TBKX6JQO.mjs.map +0 -7
  407. package/dist/lib/neutral/chunk-TU3GW67D.mjs.map +0 -7
  408. package/dist/lib/neutral/chunk-UBEZSGXY.mjs.map +0 -7
  409. package/dist/lib/neutral/chunk-UI6MWK5W.mjs.map +0 -7
  410. package/dist/lib/neutral/chunk-V36VO5SS.mjs.map +0 -7
  411. package/dist/lib/neutral/chunk-WAK4DMFV.mjs.map +0 -7
  412. package/dist/lib/neutral/chunk-YAHXAYOW.mjs +0 -56
  413. package/dist/lib/neutral/chunk-YAHXAYOW.mjs.map +0 -7
  414. package/dist/lib/neutral/chunk-YS6Q3XAD.mjs +0 -50
  415. package/dist/lib/neutral/chunk-YS6Q3XAD.mjs.map +0 -7
  416. package/dist/types/src/Extension.d.ts +0 -80
  417. package/dist/types/src/Extension.d.ts.map +0 -1
  418. package/dist/types/src/Extension.test.d.ts +0 -2
  419. package/dist/types/src/Extension.test.d.ts.map +0 -1
  420. package/dist/types/src/SchemaRegistry.d.ts +0 -84
  421. package/dist/types/src/SchemaRegistry.d.ts.map +0 -1
  422. package/dist/types/src/internal/Obj/ids.d.ts +0 -6
  423. package/dist/types/src/internal/Obj/ids.d.ts.map +0 -1
  424. package/dist/types/src/internal/Query.d.ts.map +0 -1
  425. package/dist/types/src/internal/Type/echo-schema.d.ts +0 -181
  426. package/dist/types/src/internal/Type/echo-schema.d.ts.map +0 -1
  427. package/dist/types/src/internal/Type/persistent-schema.d.ts +0 -20
  428. package/dist/types/src/internal/Type/persistent-schema.d.ts.map +0 -1
  429. package/src/Extension.test.ts +0 -235
  430. package/src/Extension.ts +0 -122
  431. package/src/SchemaRegistry.ts +0 -106
  432. package/src/internal/Obj/ids.ts +0 -12
  433. package/src/internal/Type/echo-schema.ts +0 -423
  434. package/src/internal/Type/persistent-schema.ts +0 -33
  435. /package/dist/lib/neutral/{Extension.mjs.map → Registry.mjs.map} +0 -0
  436. /package/dist/lib/neutral/{SchemaRegistry.mjs.map → Scope.mjs.map} +0 -0
  437. /package/dist/lib/neutral/{chunk-7RO7CPBZ.mjs.map → chunk-IGK6FN65.mjs.map} +0 -0
@@ -0,0 +1,74 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Option from 'effect/Option';
6
+
7
+ import { deepMapValues } from '@dxos/util';
8
+
9
+ import type * as Annotation from '../../Annotation';
10
+ import type * as Entity from '../../Entity';
11
+ import { getMetaChecked } from '../common/api/meta';
12
+ import { type Mutable } from '../common/proxy/reactive';
13
+ import { getDatabase } from '../Entity/api';
14
+ import { isEntity, isSnapshot } from '../Entity/guard';
15
+ import { Ref, getRefSavedTarget } from '../Ref';
16
+ import { getDictionary, setDictionary } from './dictionary';
17
+
18
+ /**
19
+ * Get the value of an annotation from an entity instance or snapshot.
20
+ */
21
+ export const get = <T>(
22
+ target: Entity.Unknown | Entity.Snapshot,
23
+ annotation: Annotation.Annotation<T>,
24
+ ): Option.Option<T> => {
25
+ if (isEntity(target) || isSnapshot(target)) {
26
+ const meta = getMetaChecked(target);
27
+ return getDictionary(meta.annotations, annotation);
28
+ } else {
29
+ throw new TypeError('Target is not an annotation target.');
30
+ }
31
+ };
32
+
33
+ /**
34
+ * Set the value of an annotation on an entity instance.
35
+ * Must be called with a mutable entity — i.e. inside an `Obj.update` callback.
36
+ */
37
+ export const set = <T>(target: Mutable<Entity.Unknown>, annotation: Annotation.Annotation<T>, value: T): void => {
38
+ if (isEntity(target)) {
39
+ const meta = getMetaChecked(target);
40
+ // Persist any unsaved Ref targets in the value into the entity's database so
41
+ // the encoded DXN resolves on read. This mirrors normal property assignment,
42
+ // where the reactive proxy links unsaved ref targets via `createRef` →
43
+ // `database.add`. `setDictionary` pre-encodes the value (`Schema.encodeSync`),
44
+ // so the live Ref never reaches the proxy's link handling and would otherwise
45
+ // be stored as a dangling reference.
46
+ persistRefTargets(target, value);
47
+ setDictionary(meta.annotations, annotation, value);
48
+ } else {
49
+ throw new TypeError('Target is not an annotation target.');
50
+ }
51
+ };
52
+
53
+ /**
54
+ * Add any unsaved Ref targets found in `value` to the host entity's database, matching the
55
+ * auto-persistence applied to refs assigned to ordinary entity properties. Refs whose target
56
+ * already lives in a database (the host's or a foreign one) are left untouched.
57
+ */
58
+ const persistRefTargets = (host: Entity.Unknown, value: unknown): void => {
59
+ const database = getDatabase(host);
60
+ if (database == null) {
61
+ return;
62
+ }
63
+
64
+ deepMapValues(value, (current, recurse) => {
65
+ if (Ref.isRef(current)) {
66
+ const refTarget = getRefSavedTarget(current);
67
+ if (refTarget != null && isEntity(refTarget) && getDatabase(refTarget) == null) {
68
+ database.add(refTarget);
69
+ }
70
+ return current;
71
+ }
72
+ return recurse(current);
73
+ });
74
+ };
@@ -2,6 +2,8 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- export * from './annotations';
6
- export * from './sorting';
5
+ export * from './dictionary';
7
6
  export * from './util';
7
+ export * from './sorting';
8
+ export * from './annotations';
9
+ export * from './entity-dictionary';
@@ -2,7 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import type * as Option from 'effect/Option';
5
+ import * as Option from 'effect/Option';
6
6
  import type * as Schema from 'effect/Schema';
7
7
  import * as SchemaAST from 'effect/SchemaAST';
8
8
 
@@ -13,7 +13,12 @@ import { EntityKind } from '../common/types';
13
13
 
14
14
  export interface AnnotationHelper<T> {
15
15
  /**
16
- * Get the annotation value from the schema.
16
+ * Get the annotation value from an Effect schema.
17
+ *
18
+ * Only accepts `Schema.Schema.Any` — to read an annotation off a `Type.Type`
19
+ * entity, unwrap it first with `Type.getSchema(entity)`. This keeps the
20
+ * annotation pipeline single-shaped and forces annotations to live on the
21
+ * source schema, not on the post-construction Type entity.
17
22
  */
18
23
  get: (schema: Schema.Schema.Any) => Option.Option<T>;
19
24
  /**
@@ -21,7 +26,11 @@ export interface AnnotationHelper<T> {
21
26
  */
22
27
  getFromAst: (ast: SchemaAST.AST) => Option.Option<T>;
23
28
  /**
24
- * Set the annotation value on the schema.
29
+ * Set the annotation on an Effect schema.
30
+ *
31
+ * Only accepts `Schema.Schema.Any` — annotations must be applied to the
32
+ * source schema BEFORE wrapping it with `Type.makeObject` / `Type.makeRelation`.
33
+ * In a pipe, place every `Annotation.X.set(...)` before the `Type.make...` step.
25
34
  */
26
35
  set: (value: T) => <S extends Schema.Schema.Any>(schema: S) => S;
27
36
  }
@@ -30,13 +39,14 @@ export interface AnnotationHelper<T> {
30
39
  * Note: only for system annotations.
31
40
  */
32
41
  // TODO(dmaretskyi): Rename to createSystemAnnotationHelper.
42
+ // TODO(dmaretskyi): REconcile with Annotation.make.
33
43
  export const createAnnotationHelper = <T>(id: symbol): AnnotationHelper<T> => {
34
44
  return {
35
45
  get: (schema) => SchemaAST.getAnnotation(schema.ast, id),
36
46
  getFromAst: (ast) => SchemaAST.getAnnotation(ast, id),
37
47
  set:
38
48
  (value) =>
39
- <S extends Schema.Schema.Any>(schema: S) =>
49
+ <S extends Schema.Schema.Any>(schema: S): S =>
40
50
  schema.annotations({ [id]: value }) as S,
41
51
  };
42
52
  };
@@ -69,13 +79,12 @@ export const makeTypeJsonSchemaAnnotation = (options: {
69
79
  assertArgument(!!options.relationSource === (options.kind === EntityKind.Relation), 'relationSource');
70
80
  assertArgument(!!options.relationTarget === (options.kind === EntityKind.Relation), 'relationTarget');
71
81
 
72
- const obj = {
73
- // TODO(dmaretskyi): Should this include the version?
74
- $id: options.identifier ?? DXN.fromTypename(options.typename).toString(),
82
+ const obj: Record<string, unknown> = {
83
+ $id: options.identifier ?? DXN.make(options.typename, options.version),
75
84
  entityKind: options.kind,
76
85
  version: options.version,
77
86
  typename: options.typename,
78
- } as any;
87
+ };
79
88
  if (options.kind === EntityKind.Relation) {
80
89
  obj.relationSource = { $ref: options.relationSource };
81
90
  obj.relationTarget = { $ref: options.relationTarget };
@@ -3,21 +3,68 @@
3
3
  //
4
4
 
5
5
  import { invariant } from '@dxos/invariant';
6
- import { type DXN } from '@dxos/keys';
6
+ import { DXN, EID, URI, type SpaceId } from '@dxos/keys';
7
7
  import { assumeType } from '@dxos/util';
8
8
 
9
9
  import type { AnyEntity } from '../common/types';
10
+ import { MetaId } from '../common/types/model-symbols';
10
11
  import { type InternalObjectProps, ObjectDatabaseId } from './model';
11
- import { getObjectDXN } from './util';
12
+ import { getObjectEchoUri } from './util';
12
13
 
13
14
  /**
14
- * Get the DXN of an entity.
15
+ * Controls the URI form returned by `getUri` and the public `*.getURI` helpers.
16
+ *
17
+ * - `'named'` — Registry key URI (`dxn:<meta.key>`) when the entity has a key in its meta;
18
+ * falls back to the default EID.
19
+ * - `'absolute'` — Fully-qualified EID with space id (`echo://<spaceId>/<entityId>`);
20
+ * falls back when no space is available.
21
+ * - `'relative'` — Local EID without space id (`echo:/<entityId>`).
22
+ *
23
+ * Omitting `prefer` preserves the existing behaviour.
24
+ */
25
+ export type GetURIOptions = {
26
+ prefer?: 'named' | 'absolute' | 'relative';
27
+ };
28
+
29
+ /**
30
+ * Get the URI of an entity.
15
31
  * Accepts both reactive entities and snapshots.
16
32
  */
17
- export const getDXN = (entity: AnyEntity): DXN => {
18
- const dxn = getObjectDXN(entity);
19
- invariant(dxn != null, 'Invalid entity.');
20
- return dxn;
33
+ export const getUri = (entity: AnyEntity, options?: GetURIOptions): URI.URI => {
34
+ const prefer = options?.prefer;
35
+
36
+ if (prefer === 'named') {
37
+ const key = (entity as any)[MetaId]?.key;
38
+ if (key) {
39
+ return (DXN.tryMake(`dxn:${key}`) ?? URI.make(key)) as URI.URI;
40
+ }
41
+ const uri = getObjectEchoUri(entity);
42
+ invariant(uri != null, 'Invalid entity.');
43
+ return uri;
44
+ }
45
+
46
+ if (prefer === 'relative') {
47
+ const eid = getObjectEchoUri(entity);
48
+ invariant(eid != null, 'Invalid entity.');
49
+ const entityId = EID.getEntityId(eid);
50
+ return entityId ? EID.make({ entityId }) : eid;
51
+ }
52
+
53
+ if (prefer === 'absolute') {
54
+ const eid = getObjectEchoUri(entity);
55
+ invariant(eid != null, 'Invalid entity.');
56
+ const entityId = EID.getEntityId(eid);
57
+ if (!entityId) {
58
+ return eid;
59
+ }
60
+ assumeType<InternalObjectProps>(entity);
61
+ const spaceId: SpaceId | undefined = entity[ObjectDatabaseId]?.spaceId ?? EID.getSpaceId(eid);
62
+ return spaceId ? EID.make({ spaceId, entityId }) : eid;
63
+ }
64
+
65
+ const uri = getObjectEchoUri(entity);
66
+ invariant(uri != null, 'Invalid entity.');
67
+ return uri;
21
68
  };
22
69
 
23
70
  /**
@@ -3,47 +3,119 @@
3
3
  //
4
4
 
5
5
  import * as Schema from 'effect/Schema';
6
- import type * as SchemaAST from 'effect/SchemaAST';
6
+ import * as SchemaAST from 'effect/SchemaAST';
7
7
  import type * as Types from 'effect/Types';
8
8
 
9
+ import { DXN, EntityId } from '@dxos/keys';
9
10
  import { type ToMutable } from '@dxos/util';
10
11
 
11
- import { type TypeMeta } from '../Annotation';
12
- import { type AnyEntity, type EntityKind, SchemaKindId } from '../common/types';
12
+ import { type TypeAnnotation, TypeAnnotationId } from '../Annotation/annotations';
13
+ import { makeTypeJsonSchemaAnnotation } from '../Annotation/util';
14
+ import { defineHiddenProperty } from '../common/proxy/define-hidden-property';
15
+ import { makeObject } from '../common/proxy/make-object';
16
+ import { getProxyTarget } from '../common/proxy/proxy-utils';
17
+ import {
18
+ type AnyEntity,
19
+ EntityKind,
20
+ InstancePhantomId,
21
+ KindId,
22
+ SchemaKindId,
23
+ StaticTypeSchemaSlot,
24
+ } from '../common/types';
25
+ import { type EntityMeta } from '../common/types/meta';
26
+ import { JsonSchemaType } from '../JsonSchema/json-schema-type';
13
27
 
14
28
  // TODO(burdon): Define Schema type for `typename` and use consistently for all DXN-like properties.
15
29
 
16
30
  // type RequiredKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? never : K }[keyof T];
17
31
  export type EchoTypeSchemaProps<T, ExtraFields = {}> = Types.Simplify<AnyEntity & ToMutable<T> & ExtraFields>;
18
32
 
33
+ /**
34
+ * Options accepted by every `Type.makeObject` / `Type.makeRelation` / type-kind
35
+ * factory. Defaults are derived from `(typename, version)` so callers normally
36
+ * pass nothing.
37
+ */
38
+ export type EchoTypeOptions = {
39
+ /**
40
+ * Override the entity id stamped on the in-memory `Type.Type` value.
41
+ *
42
+ * Defaults to `EntityId.deterministic(typename, version)` — stable across processes
43
+ * and workerd-safe (no `crypto.getRandomValues()` at module-evaluation time).
44
+ * Pass an explicit id (typically `EntityId.random()`) to opt out of the
45
+ * deterministic default.
46
+ */
47
+ id?: EntityId;
48
+ };
49
+
50
+ /**
51
+ * In-memory `Type.Type` entity shape produced by `Type.makeObject(dxn)` /
52
+ * `Type.makeRelation({...})`. A live reactive `TypeSchema` instance —
53
+ * identical to a persisted `Type.Type` except for database attachment.
54
+ *
55
+ * NOT a `Schema.Schema`. The underlying Effect Schema is cached on the hidden
56
+ * `StaticTypeSchemaSlot` slot — retrieve it via `Type.getSchema(...)`.
57
+ */
19
58
  // TODO(burdon): Rename EchoEntitySchema.
20
59
  export interface EchoTypeSchema<
21
60
  Self extends Schema.Schema.Any,
22
61
  ExtraFields = {},
23
62
  K extends EntityKind = EntityKind,
24
63
  Fields extends Schema.Struct.Fields = Schema.Struct.Fields,
25
- >
26
- extends
27
- TypeMeta,
28
- Schema.AnnotableClass<
29
- EchoTypeSchema<Self, ExtraFields, K, Fields>,
30
- EchoTypeSchemaProps<Schema.Schema.Type<Self>, ExtraFields>,
31
- EchoTypeSchemaProps<Schema.Schema.Encoded<Self>, ExtraFields>,
32
- Schema.Schema.Context<Self>
33
- > {
64
+ > {
34
65
  /**
35
- * Schema kind key that marks this as an ECHO schema and indicates its kind.
36
- * Makes EchoTypeSchema satisfy the Type.AnyObj or Type.Relation.Any type.
66
+ * Entity-kind brand. Type entities are their own kind (`Type`) regardless of
67
+ * the kind of instance they describe `[SchemaKindId]` carries the latter.
68
+ * This lets predicates like `Obj.isObject` / `Relation.isRelation` cleanly
69
+ * reject type entities without also having to inspect `[SchemaKindId]`.
37
70
  */
71
+ readonly [KindId]: EntityKind.Type;
72
+
73
+ /** Schema-kind brand indicating what kind of instance this type describes. */
38
74
  readonly [SchemaKindId]: K;
39
75
 
40
76
  /**
41
- * The fields defined in the original struct schema.
42
- * Allows accessing field definitions for introspection.
77
+ * Entity id. Always present stamped at construction — but NOT the type's
78
+ * identity while in-memory: an unattached type resolves its URI to the typename
79
+ * DXN, switching to `echo:/<id>` only once attached to a database (see
80
+ * `getTypeURIFromSpecifier`, which discriminates by database attachment).
43
81
  */
82
+ readonly id: EntityId;
83
+
84
+ /** Source Effect Schema (kept on a hidden slot for `Type.getSchema`). */
85
+ readonly [StaticTypeSchemaSlot]: Schema.Schema.AnyNoContext;
86
+
87
+ // NOTE: `typename` / `version` are intentionally NOT fields. They live in
88
+ // `EntityMeta` (`key` / `version`); read via `Type.getTypename(self)` /
89
+ // `Type.getVersion(self)`.
90
+ readonly jsonSchema: JsonSchemaType;
91
+
92
+ /** Struct fields for introspection. */
44
93
  readonly fields: Fields;
45
94
 
46
- instanceOf(value: unknown): boolean;
95
+ /** Phantom — instance type produced by `Obj.make(self, ...)`. */
96
+ readonly _instance?: EchoTypeSchemaProps<Schema.Schema.Type<Self>, ExtraFields>;
97
+
98
+ /**
99
+ * Phantom slot mirroring `Type<A>` so internal helpers (`makeObject`,
100
+ * `createObject`, `Ref.make`) infer the instance type uniformly whether
101
+ * the caller passes an `EchoTypeSchema` or a top-level `Type.Type` entity.
102
+ *
103
+ * Includes the instance-kind brand (`[KindId]`) so the phantom is assignable
104
+ * to the matching public-side interface in `Type.ts` (`Type.Obj` /
105
+ * `Type.Relation` / `Type.Type`). Each kind projects identity: instances of
106
+ * an object-kind schema are object-kind entities, type-kind schemas produce
107
+ * type-kind (persisted Type.Type) entities — the latter additionally carry
108
+ * the `[SchemaKindId]` / `[StaticTypeSchemaSlot]` brands the echo-handler
109
+ * proxy exposes on persisted Type entities.
110
+ */
111
+ readonly [InstancePhantomId]?: EchoTypeSchemaProps<Schema.Schema.Type<Self>, ExtraFields> & {
112
+ readonly [KindId]: K;
113
+ } & (K extends EntityKind.Type
114
+ ? {
115
+ readonly [SchemaKindId]: EntityKind.Type;
116
+ readonly [StaticTypeSchemaSlot]: Schema.Schema.AnyNoContext;
117
+ }
118
+ : {});
47
119
  }
48
120
 
49
121
  // type MakeProps =
@@ -77,8 +149,60 @@ export interface EchoTypeSchema<
77
149
  // const _getDisableValidationMakeOption = (options: MakeProps | undefined): boolean =>
78
150
  // Predicate.isBoolean(options) ? options : options?.disableValidation ?? false;
79
151
 
152
+ /**
153
+ * Identity (typename + version) of the type meta-schema — the `Type.Type` that
154
+ * every ECHO type entity is itself an instance of. Shared by the materialisation
155
+ * vehicle ({@link persistentEntitySchema}) and `TypeSchema` so the two cannot
156
+ * drift on identity.
157
+ */
158
+ export const TypeMetaSchemaDXN = DXN.make('org.dxos.type.schema', '0.1.0');
159
+
160
+ /**
161
+ * Effect Schema that every `Type.Type` entity is an instance of: the meta-schema
162
+ * struct `{ name?, jsonSchema, id }` branded as a type-kind ECHO entity. This is
163
+ * the materialisation vehicle for `makeObject` below — the canonical user-facing
164
+ * entity is `Type/type-schema.ts`'s `TypeSchema`, which carries the same shape
165
+ * plus UI annotations.
166
+ *
167
+ * Kept self-contained (no import of `TypeSchema`) to avoid a bootstrap cycle:
168
+ * `TypeSchema` is itself produced via `makeEchoTypeSchema`, so this builder must
169
+ * not depend on it. `jsonSchema` is declared optional here (only on the
170
+ * materialisation vehicle — the canonical `TypeSchema` keeps it required) so the
171
+ * construction-time `Schema.asserts` does not force the field before it is
172
+ * attached; it is populated immediately after via a lazy accessor (see
173
+ * `makeEchoTypeSchema`).
174
+ */
175
+ // TODO(wittjosiah): Reconcile with `TypeSchema` (`Type/type-schema.ts`).
176
+ // Both describe the same `org.dxos.type.schema` shape.
177
+ const persistentEntitySchema: Schema.Schema.AnyNoContext = (() => {
178
+ const typename = DXN.getName(TypeMetaSchemaDXN);
179
+ const version = DXN.getVersion(TypeMetaSchemaDXN)!;
180
+ const struct = Schema.Struct({
181
+ name: Schema.optional(Schema.String),
182
+ jsonSchema: JsonSchemaType.pipe(Schema.optional),
183
+ id: EntityId,
184
+ });
185
+ const ast = SchemaAST.annotations(struct.ast, {
186
+ [TypeAnnotationId]: { kind: EntityKind.Type, typename, version } satisfies TypeAnnotation,
187
+ [SchemaAST.JSONSchemaAnnotationId]: makeTypeJsonSchemaAnnotation({ kind: EntityKind.Type, typename, version }),
188
+ });
189
+ return Schema.make(ast);
190
+ })();
191
+
80
192
  /**
81
193
  * @internal
194
+ *
195
+ * Build an in-memory `Type.Type` entity (the value returned by `Type.makeObject`
196
+ * / `Type.makeRelation`). The result is a LIVE reactive `TypeSchema`
197
+ * instance — identical in every respect to a persisted `Type.Type` except that
198
+ * it is not yet attached to a database. It is mutable via `Type.update`, can be
199
+ * passed to `db.add(...)` (which keeps the same proxy and swaps the handler),
200
+ * and round-trips through `jsonSchema`.
201
+ *
202
+ * The source Effect Schema describing the user's type is cached on
203
+ * `[StaticTypeSchemaSlot]` so `Type.getSchema(...)` returns it without a
204
+ * jsonSchema round-trip; the cache is invalidated by the proxy set-trap when
205
+ * `jsonSchema` is mutated (see `typed-handler.ts`).
82
206
  */
83
207
  export const makeEchoTypeSchema = <
84
208
  Self extends Schema.Schema.Any,
@@ -91,38 +215,63 @@ export const makeEchoTypeSchema = <
91
215
  typename: string,
92
216
  version: string,
93
217
  kind: K,
218
+ computeJsonSchema: () => JsonSchemaType,
219
+ explicitId?: EntityId,
94
220
  ): EchoTypeSchema<Self, {}, K, Fields> => {
95
- return class EchoObjectSchemaClass extends Schema.make<
221
+ // Source Effect Schema describing the user's type — cached for `Type.getSchema`.
222
+ const sourceSchema = Schema.make<
96
223
  EchoTypeSchemaProps<Schema.Schema.Type<Self>>,
97
224
  EchoTypeSchemaProps<Schema.Schema.Encoded<Self>>,
98
225
  Schema.Schema.Context<Self>
99
- >(ast) {
100
- static readonly typename = typename;
101
- static readonly version = version;
102
- static readonly [SchemaKindId] = kind;
103
- static readonly fields = fields;
104
-
105
- static override annotations(
106
- annotations: Schema.Annotations.GenericSchema<EchoTypeSchemaProps<Schema.Schema.Type<Self>>>,
107
- ): EchoTypeSchema<Self, {}, K, Fields> {
108
- const schema = Schema.make<EchoTypeSchemaProps<Schema.Schema.Type<Self>>>(ast).annotations(annotations);
109
- return makeEchoTypeSchema<Self, K, Fields>(fields, schema.ast, typename, version, kind);
110
- }
111
-
112
- // static make(
113
- // props: RequiredKeys<Schema.TypeLiteral.Constructor<Fields, []>> extends never
114
- // ? void | Simplify<Schema.TypeLiteral.Constructor<Fields, []>>
115
- // : Simplify<Schema.TypeLiteral.Constructor<Fields, []>>,
116
- // options?: MakeProps,
117
- // ): Simplify<Schema.TypeLiteral.Type<Fields, []>> {
118
- // const propsWithDefaults: any = _lazilyMergeDefaults(fields, { ...(props as any) });
119
- // return _getDisableValidationMakeOption(options)
120
- // ? propsWithDefaults
121
- // : ParseResult.validateSync(this)(propsWithDefaults);
122
- // }
123
-
124
- static instanceOf(value: unknown): boolean {
125
- return Schema.is(this)(value);
126
- }
127
- };
226
+ >(ast);
227
+
228
+ // `typename` / `version` route through `EntityMeta` (`key` / `version`) — the
229
+ // canonical registry-provenance pair — not data fields. `keys` is empty for
230
+ // in-memory declarations until persisted.
231
+ const meta: Partial<EntityMeta> = { keys: [], key: typename, version };
232
+
233
+ // Default to a deterministic id derived from `(typename, version)` so that
234
+ // constructing a `Type.Type` entity never reaches `crypto.getRandomValues()`.
235
+ // Cloudflare workerd forbids RNG calls in global scope, and the ~hundreds of
236
+ // `Type.makeObject(...)` call sites across the monorepo execute at module top.
237
+ // `setIdOnTarget` (see `proxy/make-object.ts`) short-circuits on a pre-supplied
238
+ // valid id, so this also bypasses the `EntityId.random()` path inside `makeObject`.
239
+ // Callers can override via `Type.makeObject(dxn, { id })` when they want a fresh
240
+ // random id (e.g. inside a request handler where workerd does allow RNG).
241
+ const id = explicitId ?? EntityId.deterministic(typename, version);
242
+
243
+ // Materialise as a live reactive meta-schema instance. `jsonSchema` is attached
244
+ // below as a getter (not passed here as data) for two reasons; see that accessor.
245
+ const entity = makeObject(persistentEntitySchema, { id } as any, meta);
246
+
247
+ const target = getProxyTarget(entity)!;
248
+ // `jsonSchema` is always available, but computed once on first read rather than at
249
+ // construction: serializing the AST walks `Schema.suspend(...)` thunks, and for a
250
+ // self-referential type (`Schema.suspend(() => Self)`) that thunk hits `Self`'s TDZ
251
+ // while we're still inside its `const` initializer. A getter also lets reads return
252
+ // the raw object instead of a child reactive proxy.
253
+ let memoizedJsonSchema: JsonSchemaType | undefined;
254
+ Object.defineProperty(target, 'jsonSchema', {
255
+ configurable: true,
256
+ enumerable: true,
257
+ get() {
258
+ return (memoizedJsonSchema ??= computeJsonSchema());
259
+ },
260
+ set(value: JsonSchemaType) {
261
+ memoizedJsonSchema = value;
262
+ },
263
+ });
264
+ // Cache the source Effect Schema (read by `Type.getSchema` via the proxy's
265
+ // `[StaticTypeSchemaSlot]` get-trap; invalidated on `jsonSchema` mutation).
266
+ defineHiddenProperty(target, StaticTypeSchemaSlot, sourceSchema);
267
+ // Schema-kind brand: what kind of instance this type describes. There is no
268
+ // database handler to derive it for in-memory entities, so stamp it directly.
269
+ defineHiddenProperty(target, SchemaKindId, kind);
270
+ // Struct fields for introspection. A getter (not a data property) so reads return
271
+ // the raw fields object rather than a child reactive proxy.
272
+ Object.defineProperty(target, 'fields', { configurable: true, enumerable: false, get: () => fields });
273
+
274
+ return entity as unknown as EchoTypeSchema<Self, {}, K, Fields>;
128
275
  };
276
+
277
+ export { isEntity } from './guard';
@@ -0,0 +1,26 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import type * as Entity from '../../Entity';
6
+ import { KindId, SnapshotKindId } from '../common/types';
7
+
8
+ /**
9
+ * Returns true if the value is an ECHO entity instance (object or relation).
10
+ */
11
+ export const isEntity = (value: unknown): value is Entity.Unknown => {
12
+ if (typeof value !== 'object' || value === null) {
13
+ return false;
14
+ }
15
+ return (value as any)[KindId] !== undefined;
16
+ };
17
+
18
+ /**
19
+ * Returns true if the value is an ECHO entity snapshot.
20
+ */
21
+ export const isSnapshot = (value: unknown): value is Entity.Snapshot => {
22
+ if (typeof value !== 'object' || value === null) {
23
+ return false;
24
+ }
25
+ return (value as any)[SnapshotKindId] !== undefined;
26
+ };
@@ -7,5 +7,7 @@ export * from './entity';
7
7
  export * from './model'; // TODO(burdon): Rename.
8
8
  export * from './object';
9
9
  export * from './relation';
10
+ export * from './type-kind';
11
+ export * from './type-uri';
10
12
  export * from './util';
11
13
  export * from './version';