@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
@@ -6,8 +6,10 @@ import type { InspectOptionsStylized, inspect as inspectFn } from 'node:util';
6
6
 
7
7
  import { type CustomInspectFunction, inspectCustom } from '@dxos/debug';
8
8
 
9
- import { getTypeDXN } from '../Annotation';
10
- import { ATTR_META, ATTR_TYPE, type AnyEntity, MetaId } from '../common/types';
9
+ import { getTypeURI } from '../Annotation';
10
+ import { ATTR_TYPE, type AnyEntity } from '../common/types';
11
+ import { ATTR_META } from '../common/types/meta';
12
+ import { MetaId } from '../common/types/model-symbols';
11
13
 
12
14
  /*
13
15
  * @internal
@@ -37,7 +39,7 @@ const typedObjectInspectFunction: CustomInspectFunction<AnyEntity> = function (
37
39
  return inspect(
38
40
  {
39
41
  id,
40
- [ATTR_TYPE]: getTypeDXN(this),
42
+ [ATTR_TYPE]: getTypeURI(this),
41
43
  ...props,
42
44
  [ATTR_META]: (this as any)[MetaId], // TODO(dmaretskyi): Couldn't use getMeta since that throw's if the object has no meta.
43
45
  },
@@ -2,25 +2,28 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import * as Schema from 'effect/Schema';
5
6
  import { describe, expect, test } from 'vitest';
6
7
 
7
- import { DXN } from '@dxos/keys';
8
+ import { DXN, EID } from '@dxos/keys';
8
9
 
9
10
  import * as Obj from '../../Obj';
10
11
  import { TestSchema } from '../../testing';
11
- import { getSchemaDXN, getSchemaTypename, getTypeDXN, getTypename } from '../Annotation';
12
+ import * as Type from '../../Type';
13
+ import { getTypeURI, getTypename } from '../Annotation';
12
14
  import { getMetaChecked } from '../common/api';
13
- import { makeObject } from '../common/proxy';
14
- import { ATTR_TYPE, EntityKind, KindId, MetaId, TypeId, getSchema } from '../common/types';
15
- import { RelationSourceId, RelationTargetId, getObjectDXN } from '../Entity';
15
+ import { ATTR_TYPE, EntityKind, KindId, TypeId, getSchema } from '../common/types';
16
+ import { MetaId } from '../common/types/model-symbols';
17
+ import { RelationSourceId, RelationTargetId, getObjectEchoUri } from '../Entity';
18
+ import * as JsonSchema from '../JsonSchema';
16
19
  import { Ref, StaticRefResolver } from '../Ref';
17
20
  import { createObject } from './create-object';
18
21
  import { objectFromJSON, objectToJSON } from './json-serializer';
19
22
 
20
23
  describe('Object JSON serializer', () => {
21
24
  test('should serialize and deserialize object', async () => {
22
- const contact = makeObject(TestSchema.Person, { name: 'Alice' });
23
- Obj.change(contact, (contact) => {
25
+ const contact = Obj.make(TestSchema.Person, { name: 'Alice' });
26
+ Obj.update(contact, (contact) => {
24
27
  getMetaChecked(contact).keys.push({ id: '12345', source: 'example.com' });
25
28
  });
26
29
 
@@ -33,13 +36,13 @@ describe('Object JSON serializer', () => {
33
36
  const taskJson = objectToJSON(task);
34
37
 
35
38
  expect(contactJson.id).toBe(contact.id);
36
- expect(contactJson[ATTR_TYPE]).toEqual(getSchemaDXN(TestSchema.Person)!.toString());
39
+ expect(contactJson[ATTR_TYPE]).toEqual(Type.getURI(TestSchema.Person).toString());
37
40
  expect(contactJson.name).toEqual('Alice');
38
41
 
39
42
  expect(taskJson.id).toBe(task.id);
40
- expect(taskJson[ATTR_TYPE]).toEqual(getSchemaDXN(TestSchema.Task)!.toString());
43
+ expect(taskJson[ATTR_TYPE]).toEqual(Type.getURI(TestSchema.Task).toString());
41
44
  expect(taskJson.title).toEqual('Fix the tests');
42
- expect(taskJson.assignee).toEqual({ '/': DXN.fromLocalObjectId(contact.id).toString() });
45
+ expect(taskJson.assignee).toEqual({ '/': EID.make({ entityId: contact.id }) });
43
46
 
44
47
  const refResolver = new StaticRefResolver()
45
48
  .addSchema(TestSchema.Person)
@@ -52,7 +55,7 @@ describe('Object JSON serializer', () => {
52
55
 
53
56
  expect(contactFromJson.id).toBe(contact.id);
54
57
  expect(contactFromJson.name).toBe('Alice');
55
- expect((contactFromJson as any)[TypeId]).toEqual(getSchemaDXN(TestSchema.Person));
58
+ expect((contactFromJson as any)[TypeId]).toEqual(Type.getURI(TestSchema.Person));
56
59
  expect((contactFromJson as any)[KindId]).toBe(EntityKind.Object);
57
60
  expect((contactFromJson as any)[RelationSourceId]).toBeUndefined();
58
61
  expect((contactFromJson as any)[RelationTargetId]).toBeUndefined();
@@ -63,23 +66,25 @@ describe('Object JSON serializer', () => {
63
66
  source: 'example.com',
64
67
  },
65
68
  ],
69
+ tags: [],
70
+ annotations: {},
66
71
  });
67
- expect(getTypeDXN(contactFromJson)?.toString()).toBe(getSchemaDXN(TestSchema.Person)!.toString());
68
- expect(getTypename(contactFromJson)).toBe(getSchemaTypename(TestSchema.Person));
69
- expect(getObjectDXN(contactFromJson)?.toString()).toEqual(getObjectDXN(contact)?.toString());
70
- expect(getSchema(contactFromJson)).toEqual(TestSchema.Person);
72
+ expect(getTypeURI(contactFromJson)?.toString()).toBe(Type.getURI(TestSchema.Person).toString());
73
+ expect(getTypename(contactFromJson)).toBe(Type.getTypename(TestSchema.Person));
74
+ expect(getObjectEchoUri(contactFromJson)?.toString()).toEqual(getObjectEchoUri(contact)?.toString());
75
+ expect(getSchema(contactFromJson)).toEqual(Type.getSchema(TestSchema.Person));
71
76
 
72
77
  expect(taskFromJson.id).toBe(task.id);
73
78
  expect(taskFromJson.title).toBe('Fix the tests');
74
- expect(taskFromJson.assignee!.dxn).toEqual(DXN.fromLocalObjectId(contact.id));
79
+ expect(taskFromJson.assignee!.uri).toEqual(EID.make({ entityId: contact.id }));
75
80
  expect(taskFromJson.assignee!.target).toEqual(contact);
76
81
  expect(await taskFromJson.assignee!.load()).toEqual(contact);
77
- expect((taskFromJson as any)[TypeId]).toEqual(getSchemaDXN(TestSchema.Task));
82
+ expect((taskFromJson as any)[TypeId]).toEqual(Type.getURI(TestSchema.Task));
78
83
  expect((taskFromJson as any)[KindId]).toBe(EntityKind.Object);
79
84
  expect((taskFromJson as any)[RelationSourceId]).toBeUndefined();
80
85
  expect((taskFromJson as any)[RelationTargetId]).toBeUndefined();
81
- expect((taskFromJson as any)[MetaId]).toEqual({ keys: [] });
82
- expect(getSchema(taskFromJson)).toEqual(TestSchema.Task);
86
+ expect((taskFromJson as any)[MetaId]).toEqual({ keys: [], tags: [], annotations: {} });
87
+ expect(getSchema(taskFromJson)).toEqual(Type.getSchema(TestSchema.Task));
83
88
  });
84
89
 
85
90
  test('serialize with unresolved schema', async () => {
@@ -90,9 +95,20 @@ describe('Object JSON serializer', () => {
90
95
  expect(contactFromJson.id).toBe(contact.id);
91
96
  expect(contactFromJson.name).toBe('Alice');
92
97
  expect(getSchema(contactFromJson)).toBeUndefined();
93
- expect(getTypename(contactFromJson)).toEqual(getSchemaTypename(TestSchema.Person));
94
- expect(getObjectDXN(contactFromJson)).toEqual(getObjectDXN(contact));
95
- expect(getTypeDXN(contactFromJson)).toEqual(getSchemaDXN(TestSchema.Person));
98
+ expect(getTypename(contactFromJson)).toEqual(Type.getTypename(TestSchema.Person));
99
+ expect(getObjectEchoUri(contactFromJson)).toEqual(getObjectEchoUri(contact));
100
+ expect(getTypeURI(contactFromJson)).toEqual(Type.getURI(TestSchema.Person));
101
+ });
102
+
103
+ test('upgrades bare string tags to encoded references on deserialize', async () => {
104
+ const expando = Obj.make(TestSchema.Expando, { message: 'hi' });
105
+ const json = objectToJSON(expando) as any;
106
+ // Simulate data serialized before the tags-as-refs migration: bare id strings.
107
+ json['@meta'] = { keys: [], tags: ['echo:/TAGLEGACY'] };
108
+
109
+ const fromJson = (await objectFromJSON(json)) as any;
110
+ // Decodes to a materialized `Ref` (the shared ref codec), not a raw encoded reference.
111
+ expect(fromJson[MetaId].tags.map((ref: any) => ref.uri)).toEqual(['echo:/TAGLEGACY']);
96
112
  });
97
113
 
98
114
  test('deserializes expando without leaking internal json keys', async () => {
@@ -117,4 +133,67 @@ describe('Object JSON serializer', () => {
117
133
  expect(expandoFromJson.message).toBe('local-only');
118
134
  expect((expandoFromJson as any)[ATTR_TYPE]).toBeUndefined();
119
135
  });
136
+
137
+ // `objectFromJSON` is the deserialization path for queue messages and devtools
138
+ // round-trips. For persisted `Type.Type` entities it must stamp `KindId = Type`
139
+ // (not Object), mirroring the kind resolution that `createObject` does for the
140
+ // in-memory path. Otherwise `Filter.type(Type.Type)` / `Type.isType` skip them.
141
+ describe('Type.Type round-trip', () => {
142
+ test('preserves KindId=Type for a persisted Type.Type entity', async ({ expect }) => {
143
+ const typeEntity = Type.makeObjectFromJsonSchema({
144
+ typename: 'com.example.type.regression',
145
+ version: '0.1.0',
146
+ jsonSchema: JsonSchema.toJsonSchema(Schema.Struct({ field: Schema.Number })),
147
+ name: 'Regression Type',
148
+ });
149
+
150
+ const typeJson = objectToJSON(typeEntity as any);
151
+ const refResolver = new StaticRefResolver().addSchema(Type.Type);
152
+ const reconstructed = (await objectFromJSON(typeJson, { refResolver })) as any;
153
+
154
+ expect(reconstructed[KindId]).toBe(EntityKind.Type);
155
+ expect(Type.isType(reconstructed)).toBe(true);
156
+ // `typename` lives in `EntityMeta.key` on persisted Type.Type entities
157
+ // — surfaced via `Type.getTypename`.
158
+ expect(Type.getTypename(reconstructed)).toBe('com.example.type.regression');
159
+ });
160
+ });
161
+
162
+ describe('Uint8Array', () => {
163
+ const Blob = Schema.Struct({
164
+ name: Schema.String,
165
+ bytes: Schema.Uint8ArrayFromSelf,
166
+ }).pipe(Type.makeObject(DXN.make('com.example.type.blob', '0.1.0')));
167
+ type Blob = Type.InstanceType<typeof Blob>;
168
+
169
+ test('round-trips Uint8Array field through JSON with schema', async ({ expect }) => {
170
+ const bytes = new Uint8Array([0, 1, 2, 3, 250, 251, 252, 253, 254, 255]);
171
+ const blob = Obj.make(Blob, { name: 'blob', bytes });
172
+
173
+ const blobJson = objectToJSON(blob);
174
+ // JSON must round-trip through stringify/parse without loss.
175
+ const roundTripped = JSON.parse(JSON.stringify(blobJson));
176
+
177
+ const refResolver = new StaticRefResolver().addSchema(Blob);
178
+ const blobFromJson = (await objectFromJSON(roundTripped, { refResolver })) as Blob;
179
+
180
+ expect(blobFromJson.name).toBe('blob');
181
+ expect(blobFromJson.bytes).toBeInstanceOf(Uint8Array);
182
+ expect(Array.from(blobFromJson.bytes)).toEqual(Array.from(bytes));
183
+ });
184
+
185
+ test('round-trips Uint8Array field through JSON without schema resolver', async ({ expect }) => {
186
+ const bytes = new Uint8Array([10, 20, 30, 40, 50]);
187
+ const blob = Obj.make(Blob, { name: 'blob', bytes });
188
+
189
+ const blobJson = objectToJSON(blob);
190
+ const roundTripped = JSON.parse(JSON.stringify(blobJson));
191
+
192
+ const blobFromJson = (await objectFromJSON(roundTripped)) as Blob;
193
+
194
+ expect(blobFromJson.name).toBe('blob');
195
+ expect(blobFromJson.bytes).toBeInstanceOf(Uint8Array);
196
+ expect(Array.from(blobFromJson.bytes)).toEqual(Array.from(bytes));
197
+ });
198
+ });
120
199
  });
@@ -5,39 +5,40 @@
5
5
  import * as Schema from 'effect/Schema';
6
6
 
7
7
  import { raise } from '@dxos/debug';
8
- import { type EncodedReference, ObjectStructure, isEncodedReference } from '@dxos/echo-protocol';
8
+ import { type EncodedReference, EntityStructure, isEncodedReference } from '@dxos/echo-protocol';
9
9
  import { assertArgument, invariant } from '@dxos/invariant';
10
- import { DXN, ObjectId } from '@dxos/keys';
11
- import { assumeType, deepMapValues, visitValues } from '@dxos/util';
10
+ import { EID, EntityId, URI } from '@dxos/keys';
11
+ import { assumeType, decodeUint8ArrayFromJson, deepMapValues, isEncodedUint8Array, visitValues } from '@dxos/util';
12
12
 
13
13
  import type * as Database from '../../Database';
14
14
  import type * as Obj from '../../Obj';
15
- import { getTypeDXN, setTypename } from '../Annotation';
15
+ import { getTypeAnnotation, getTypeURI, setTypename } from '../Annotation';
16
16
  import { attachTypedJsonSerializer, defineHiddenProperty, typedJsonSerializer } from '../common/proxy';
17
17
  import {
18
- ATTR_META,
19
18
  ATTR_PARENT,
20
19
  ATTR_TYPE,
21
20
  type AnyEntity,
22
21
  EntityKind,
23
22
  KindId,
24
- MetaId,
25
- ObjectMetaSchema,
26
23
  ParentId,
27
24
  setSchema,
25
+ setType,
28
26
  } from '../common/types';
27
+ import { ATTR_META, EntityMetaSchema } from '../common/types/meta';
28
+ import { MetaId } from '../common/types/model-symbols';
29
29
  import {
30
30
  ATTR_DELETED,
31
31
  ATTR_RELATION_SOURCE,
32
32
  ATTR_RELATION_TARGET,
33
- ATTR_SELF_DXN,
33
+ ATTR_SELF_URI,
34
+ ATTR_SELF_URI_LEGACY,
34
35
  ObjectDatabaseId,
35
36
  type ObjectJSON,
36
37
  RelationSourceDXNId,
37
38
  RelationSourceId,
38
39
  RelationTargetDXNId,
39
40
  RelationTargetId,
40
- SelfDXNId,
41
+ SelfURIId,
41
42
  assertObjectModel,
42
43
  } from '../Entity';
43
44
  import { Ref, type RefResolver, refFromEncodedReference, setRefResolver } from '../Ref';
@@ -62,7 +63,7 @@ type SerializedObject<T extends { id: string }> = {
62
63
  * Converts object to it's JSON representation.
63
64
  */
64
65
  export const objectToJSON = <T extends AnyEntity>(obj: T): SerializedObject<T> => {
65
- const typename = getTypeDXN(obj)?.toString();
66
+ const typename = getTypeURI(obj);
66
67
  invariant(typename && typeof typename === 'string');
67
68
  return typedJsonSerializer.call(obj);
68
69
  };
@@ -75,27 +76,27 @@ export const objectToJSON = <T extends AnyEntity>(obj: T): SerializedObject<T> =
75
76
  *
76
77
  * @param jsonData - JSON representation of the object.
77
78
  * @param options.refResolver - Resolver for references.
78
- * @param options.dxn - Override object DXN.
79
+ * @param options.uri - Override object URI.
79
80
  * @param options.database - Database to associate with the object.
80
81
  */
81
82
  export const objectFromJSON = async (
82
83
  jsonData: unknown,
83
84
  {
84
85
  refResolver,
85
- dxn,
86
+ uri,
86
87
  database,
87
88
  parent,
88
- }: { refResolver?: RefResolver; dxn?: DXN; database?: Database.Database; parent?: Obj.Unknown } = {},
89
+ }: { refResolver?: RefResolver; uri?: URI.URI; database?: Database.Database; parent?: Obj.Unknown } = {},
89
90
  ): Promise<AnyEntity> => {
90
91
  assumeType<ObjectJSON>(jsonData);
91
92
  assertArgument(typeof jsonData === 'object' && jsonData !== null, 'jsonData', 'expect object');
92
93
  assertArgument(typeof jsonData[ATTR_TYPE] === 'string', 'jsonData[ATTR_TYPE]', 'expected object to have a type');
93
94
  assertArgument(typeof jsonData.id === 'string', 'jsonData.id', 'expected object to have an id');
94
95
 
95
- const type = DXN.parse(jsonData[ATTR_TYPE]);
96
+ const type = URI.make(jsonData[ATTR_TYPE]);
96
97
  const schema = await refResolver?.resolveSchema(type);
97
98
  invariant(schema === undefined || Schema.isSchema(schema));
98
- const decodedInput = stripInternalJsonKeys(jsonData);
99
+ const decodedInput = restoreUint8Arrays(stripInternalJsonKeys(jsonData));
99
100
 
100
101
  let obj: any;
101
102
  if (schema != null) {
@@ -107,17 +108,26 @@ export const objectFromJSON = async (
107
108
  obj = decodeGeneric(decodedInput, { refResolver });
108
109
  }
109
110
 
110
- invariant(ObjectId.isValid(obj.id), 'Invalid object id');
111
+ invariant(EntityId.isValid(obj.id), 'Invalid object id');
111
112
  setTypename(obj, type);
112
113
  if (schema) {
113
114
  setSchema(obj, schema);
114
115
  }
116
+ // Resolve and stamp the source type entity, if the resolver provides one.
117
+ // Lets `Obj.getType` / `Entity.getType` return a stable entity for objects
118
+ // loaded via `Obj.fromJSON` (serializer / queue paths).
119
+ if (refResolver?.resolveType) {
120
+ const typeEntity = await refResolver.resolveType(type);
121
+ if (typeEntity != null) {
122
+ setType(obj, typeEntity);
123
+ }
124
+ }
115
125
 
116
126
  const isRelation =
117
127
  typeof jsonData[ATTR_RELATION_SOURCE] === 'string' || typeof jsonData[ATTR_RELATION_TARGET] === 'string';
118
128
  if (isRelation) {
119
- const sourceDxn: DXN = DXN.parse(jsonData[ATTR_RELATION_SOURCE] ?? raise(new TypeError('Missing relation source')));
120
- const targetDxn: DXN = DXN.parse(jsonData[ATTR_RELATION_TARGET] ?? raise(new TypeError('Missing relation target')));
129
+ const sourceDxn = jsonData[ATTR_RELATION_SOURCE] ?? raise(new TypeError('Missing relation source'));
130
+ const targetDxn = jsonData[ATTR_RELATION_TARGET] ?? raise(new TypeError('Missing relation target'));
121
131
 
122
132
  const source = (await refResolver?.resolve(sourceDxn)) as AnyEntity | undefined;
123
133
  const target = (await refResolver?.resolve(targetDxn)) as AnyEntity | undefined;
@@ -128,29 +138,37 @@ export const objectFromJSON = async (
128
138
  defineHiddenProperty(obj, RelationSourceId, source);
129
139
  defineHiddenProperty(obj, RelationTargetId, target);
130
140
  } else {
131
- defineHiddenProperty(obj, KindId, EntityKind.Object);
141
+ // Honour the schema's TypeAnnotation kind — persisted `Type.Type` entities
142
+ // (e.g. dynamic schemas loaded from a snapshot import) must brand as
143
+ // `KindId = Type`, not Object, otherwise `Filter.type(Type.Type)` /
144
+ // `Type.isType` skip them and the schema registry never picks them up.
145
+ // Mirrors the kind resolution in `createObject` (the in-memory path).
146
+ const annotationKind = schema != null ? getTypeAnnotation(schema)?.kind : undefined;
147
+ defineHiddenProperty(obj, KindId, annotationKind === EntityKind.Type ? EntityKind.Type : EntityKind.Object);
132
148
  }
133
149
 
134
150
  if (typeof jsonData[ATTR_META] === 'object') {
135
- const meta = await ObjectMetaSchema.pipe(Schema.decodeUnknownPromise)(jsonData[ATTR_META]);
151
+ const meta = await EntityMetaSchema.pipe(Schema.decodeUnknownPromise)(normalizeMeta(jsonData[ATTR_META]));
136
152
  invariant(Array.isArray(meta.keys));
137
153
  defineHiddenProperty(obj, MetaId, meta);
138
154
  } else {
139
155
  defineHiddenProperty(obj, MetaId, {
140
156
  keys: [],
157
+ tags: [],
158
+ annotations: {},
141
159
  });
142
160
  }
143
161
 
144
162
  if (jsonData[ATTR_PARENT]) {
145
- const parentDxn = DXN.parse(jsonData[ATTR_PARENT]);
163
+ const parentDxn = jsonData[ATTR_PARENT];
146
164
  const resolvedParent = (await refResolver?.resolve(parentDxn)) as Obj.Unknown | undefined;
147
165
  defineHiddenProperty(obj, ParentId, resolvedParent);
148
166
  } else if (parent) {
149
167
  defineHiddenProperty(obj, ParentId, parent);
150
168
  }
151
169
 
152
- if (dxn) {
153
- defineHiddenProperty(obj, SelfDXNId, dxn);
170
+ if (uri) {
171
+ defineHiddenProperty(obj, SelfURIId, uri);
154
172
  }
155
173
 
156
174
  if (database) {
@@ -161,12 +179,30 @@ export const objectFromJSON = async (
161
179
  invariant((obj as any)[ATTR_TYPE] === undefined, 'Invalid object model');
162
180
  invariant((obj as any)[ATTR_META] === undefined, 'Invalid object model');
163
181
  invariant((obj as any)[ATTR_DELETED] === undefined, 'Invalid object model');
164
- invariant((obj as any)[ATTR_SELF_DXN] === undefined, 'Invalid object model');
182
+ invariant((obj as any)[ATTR_SELF_URI] === undefined, 'Invalid object model');
183
+ invariant((obj as any)[ATTR_SELF_URI_LEGACY] === undefined, 'Invalid object model');
165
184
  invariant((obj as any)[ATTR_RELATION_SOURCE] === undefined, 'Invalid object model');
166
185
  invariant((obj as any)[ATTR_RELATION_TARGET] === undefined, 'Invalid object model');
167
186
  return obj;
168
187
  };
169
188
 
189
+ /**
190
+ * Backfills required meta fields and upgrades legacy `tags` (bare URI strings) to encoded references
191
+ * so serialized data produced before the tags-as-refs migration still decodes.
192
+ */
193
+ const normalizeMeta = (meta: any): any => {
194
+ const tags = Array.isArray(meta?.tags)
195
+ ? meta.tags.map((tag: unknown) => (typeof tag === 'string' ? { '/': URI.make(tag) } : tag))
196
+ : [];
197
+ // Coalesce required fields so explicit `undefined` in legacy input doesn't override the defaults.
198
+ return {
199
+ ...meta,
200
+ keys: Array.isArray(meta?.keys) ? meta.keys : [],
201
+ tags,
202
+ annotations: meta?.annotations ?? {},
203
+ };
204
+ };
205
+
170
206
  const decodeGeneric = (jsonData: unknown, options: { refResolver?: RefResolver }) => {
171
207
  const props = stripInternalJsonKeys(jsonData);
172
208
 
@@ -174,17 +210,33 @@ const decodeGeneric = (jsonData: unknown, options: { refResolver?: RefResolver }
174
210
  if (isEncodedReference(value)) {
175
211
  return refFromEncodedReference(value, options.refResolver);
176
212
  }
213
+ if (isEncodedUint8Array(value)) {
214
+ return decodeUint8ArrayFromJson(value);
215
+ }
177
216
 
178
217
  return visitor(value);
179
218
  });
180
219
  };
181
220
 
221
+ /**
222
+ * Recursively replaces encoded `Uint8Array` JSON markers with actual `Uint8Array` instances.
223
+ * Runs before schema decoding so `Schema.Uint8ArrayFromSelf` sees real bytes.
224
+ */
225
+ const restoreUint8Arrays = (data: unknown): any =>
226
+ deepMapValues(data, (value, recurse) => {
227
+ if (isEncodedUint8Array(value)) {
228
+ return decodeUint8ArrayFromJson(value);
229
+ }
230
+ return recurse(value);
231
+ });
232
+
182
233
  const stripInternalJsonKeys = (jsonData: unknown) => {
183
234
  const {
184
235
  [ATTR_TYPE]: _type,
185
236
  [ATTR_META]: _meta,
186
237
  [ATTR_DELETED]: _deleted,
187
- [ATTR_SELF_DXN]: _selfDxn,
238
+ [ATTR_SELF_URI]: _selfUri,
239
+ [ATTR_SELF_URI_LEGACY]: _legacySelfUri,
188
240
  [ATTR_RELATION_SOURCE]: _relationSource,
189
241
  [ATTR_RELATION_TARGET]: _relationTarget,
190
242
  ...props
@@ -206,17 +258,21 @@ export const setRefResolverOnData = (obj: AnyEntity, refResolver: RefResolver) =
206
258
  };
207
259
 
208
260
  /**
209
- * Convert ObjectStructure to JSON data for indexing.
210
- * Different from {@link objectToJSON} as it takes the internal {@link ObjectStructure} representation directly
261
+ * Convert EntityStructure to JSON data for indexing.
262
+ * Different from {@link objectToJSON} as it takes the internal {@link EntityStructure} representation directly
211
263
  */
212
- export const objectStructureToJson = (objectId: string, structure: ObjectStructure): Obj.JSON => {
264
+ export const objectStructureToJson = (objectId: EntityId, structure: EntityStructure): Obj.JSON => {
265
+ const typeRef = EntityStructure.getTypeReference(structure)?.['/'];
266
+ const parent = EntityStructure.getParent(structure)?.['/'];
267
+ const source = EntityStructure.getRelationSource(structure)?.['/'];
268
+ const target = EntityStructure.getRelationTarget(structure)?.['/'];
213
269
  return {
214
270
  ...structure.data,
215
271
  id: objectId,
216
- [ATTR_TYPE]: (ObjectStructure.getTypeReference(structure)?.['/'] ?? '') as DXN.String,
217
- [ATTR_DELETED]: ObjectStructure.isDeleted(structure),
218
- [ATTR_PARENT]: ObjectStructure.getParent(structure)?.['/'] as DXN.String | undefined,
219
- [ATTR_RELATION_SOURCE]: ObjectStructure.getRelationSource(structure)?.['/'] as DXN.String | undefined,
220
- [ATTR_RELATION_TARGET]: ObjectStructure.getRelationTarget(structure)?.['/'] as DXN.String | undefined,
272
+ [ATTR_TYPE]: typeRef ? URI.make(typeRef) : undefined,
273
+ [ATTR_DELETED]: EntityStructure.isDeleted(structure),
274
+ [ATTR_PARENT]: parent !== undefined ? EID.tryParse(parent) : undefined,
275
+ [ATTR_RELATION_SOURCE]: source !== undefined ? EID.tryParse(source) : undefined,
276
+ [ATTR_RELATION_TARGET]: target !== undefined ? EID.tryParse(target) : undefined,
221
277
  };
222
278
  };
@@ -5,6 +5,8 @@
5
5
  import * as Schema from 'effect/Schema';
6
6
  import { describe, test } from 'vitest';
7
7
 
8
+ import { DXN } from '@dxos/keys';
9
+
8
10
  import * as Obj from '../../Obj';
9
11
  import { TestSchema } from '../../testing';
10
12
  import * as Type from '../../Type';
@@ -17,7 +19,7 @@ describe('Obj.setValue', () => {
17
19
  email: 'john@example.com',
18
20
  });
19
21
 
20
- Obj.change(person, (person) => Obj.setValue(person, ['address', 'city'], 'NYC'));
22
+ Obj.update(person, (person) => Obj.setValue(person, ['address', 'city'], 'NYC'));
21
23
 
22
24
  expect(person.address).toBeDefined();
23
25
  expect(person.address?.city).toBe('NYC');
@@ -30,7 +32,7 @@ describe('Obj.setValue', () => {
30
32
  email: 'john@example.com',
31
33
  });
32
34
 
33
- Obj.change(person, (person) => Obj.setValue(person, ['fields', 0, 'label'], 'Phone'));
35
+ Obj.update(person, (person) => Obj.setValue(person, ['fields', 0, 'label'], 'Phone'));
34
36
 
35
37
  expect(Array.isArray(person.fields)).toBe(true);
36
38
  expect(person.fields?.[0].label).toBe('Phone');
@@ -45,7 +47,7 @@ describe('Obj.setValue', () => {
45
47
  email: 'john@example.com',
46
48
  });
47
49
 
48
- Obj.change(person, (person) => Obj.setValue(person, ['address', 'coordinates', 'lat'], 40.7128));
50
+ Obj.update(person, (person) => Obj.setValue(person, ['address', 'coordinates', 'lat'], 40.7128));
49
51
 
50
52
  expect(person.address).toBeDefined();
51
53
  expect(person.address?.coordinates).toBeDefined();
@@ -60,16 +62,11 @@ describe('Obj.setValue', () => {
60
62
  const Container = Schema.Struct({
61
63
  name: Schema.String,
62
64
  items: Schema.optional(Schema.Array(Item)),
63
- }).pipe(
64
- Type.object({
65
- typename: 'test.com/Container',
66
- version: '0.1.0',
67
- }),
68
- );
65
+ }).pipe(Type.makeObject(DXN.make('com.test.type.container', '0.1.0')));
69
66
 
70
67
  const container = Obj.make(Container, { name: 'box' });
71
68
 
72
- Obj.change(container, (container) => {
69
+ Obj.update(container, (container) => {
73
70
  Obj.setValue(container, ['items', 0, 'value'], 10);
74
71
  Obj.setValue(container, ['items', 1, 'value'], 20);
75
72
  Obj.setValue(container, ['items', 2, 'value'], 30);
@@ -88,7 +85,7 @@ describe('Obj.setValue', () => {
88
85
  email: 'john@example.com',
89
86
  });
90
87
 
91
- Obj.change(person, (person) => Obj.setValue(person, ['age'], 25));
88
+ Obj.update(person, (person) => Obj.setValue(person, ['age'], 25));
92
89
 
93
90
  expect(person.age).toBe(25);
94
91
  });
@@ -100,7 +97,7 @@ describe('Obj.setValue', () => {
100
97
  email: 'john@example.com',
101
98
  });
102
99
 
103
- Obj.change(person, (person) => Obj.setValue(person, ['address', 'city'], 'NYC'));
100
+ Obj.update(person, (person) => Obj.setValue(person, ['address', 'city'], 'NYC'));
104
101
 
105
102
  expect(person.address).toBeDefined();
106
103
  expect(person.address?.city).toBe('NYC');
@@ -114,7 +111,7 @@ describe('Obj.setValue', () => {
114
111
  });
115
112
 
116
113
  let result: any;
117
- Obj.change(person, (person) => {
114
+ Obj.update(person, (person) => {
118
115
  result = Obj.setValue(person, ['age'], 30);
119
116
  });
120
117
 
@@ -129,7 +126,7 @@ describe('Obj.setValue', () => {
129
126
  age: 25,
130
127
  });
131
128
 
132
- Obj.change(person, (person) => Obj.setValue(person, ['age'], 30));
129
+ Obj.update(person, (person) => Obj.setValue(person, ['age'], 30));
133
130
 
134
131
  expect(person.age).toBe(30);
135
132
  });
@@ -142,7 +139,7 @@ describe('Obj.setValue', () => {
142
139
  address: { city: 'Boston', state: 'MA', coordinates: {} },
143
140
  });
144
141
 
145
- Obj.change(person, (person) => Obj.setValue(person, ['address', 'city'], 'NYC'));
142
+ Obj.update(person, (person) => Obj.setValue(person, ['address', 'city'], 'NYC'));
146
143
 
147
144
  expect(person.address?.city).toBe('NYC');
148
145
  expect(person.address?.state).toBe('MA');
@@ -151,16 +148,11 @@ describe('Obj.setValue', () => {
151
148
  test('handles two-dimensional arrays', ({ expect }) => {
152
149
  const Matrix = Schema.Struct({
153
150
  values: Schema.optional(Schema.Array(Schema.Array(Schema.Number))),
154
- }).pipe(
155
- Type.object({
156
- typename: 'test.com/Matrix',
157
- version: '0.1.0',
158
- }),
159
- );
151
+ }).pipe(Type.makeObject(DXN.make('com.test.type.matrix', '0.1.0')));
160
152
 
161
153
  const matrix = Obj.make(Matrix, {});
162
154
 
163
- Obj.change(matrix, (matrix) => {
155
+ Obj.update(matrix, (matrix) => {
164
156
  Obj.setValue(matrix, ['values', 0, 0], 1);
165
157
  Obj.setValue(matrix, ['values', 0, 1], 2);
166
158
  Obj.setValue(matrix, ['values', 1, 0], 3);
@@ -180,7 +172,7 @@ describe('Obj.setValue', () => {
180
172
  email: 'john@example.com',
181
173
  });
182
174
 
183
- Obj.change(person, (person) => {
175
+ Obj.update(person, (person) => {
184
176
  expect(() => Obj.setValue(person, [], 'value')).toThrow('Path must not be empty');
185
177
  });
186
178
  });
@@ -192,7 +184,7 @@ describe('Obj.setValue', () => {
192
184
  email: 'john@example.com',
193
185
  });
194
186
 
195
- Obj.change(person, (person) => Obj.setValue(person, ['age'], 30));
187
+ Obj.update(person, (person) => Obj.setValue(person, ['age'], 30));
196
188
 
197
189
  expect(person.age).toBe(30);
198
190
  });
@@ -205,17 +197,12 @@ describe('Obj.setValue', () => {
205
197
  const Container = Schema.Struct({
206
198
  name: Schema.String,
207
199
  items: Schema.optional(Schema.Array(Item)),
208
- }).pipe(
209
- Type.object({
210
- typename: 'test.com/Container',
211
- version: '0.1.0',
212
- }),
213
- );
200
+ }).pipe(Type.makeObject(DXN.make('com.test.type.container', '0.1.0')));
214
201
 
215
202
  const container = Obj.make(Container, { name: 'box' });
216
203
 
217
204
  // Using string '0' for array index.
218
- Obj.change(container, (container) => Obj.setValue(container, ['items', '0', 'value'], 42));
205
+ Obj.update(container, (container) => Obj.setValue(container, ['items', '0', 'value'], 42));
219
206
 
220
207
  expect(container.items?.[0].value).toBe(42);
221
208
  });
@@ -232,18 +219,13 @@ describe('Obj.setValue', () => {
232
219
  const TodoList = Schema.Struct({
233
220
  name: Schema.String,
234
221
  tasks: Schema.optional(Schema.Array(Task)),
235
- }).pipe(
236
- Type.object({
237
- typename: 'test.com/TodoList',
238
- version: '0.1.0',
239
- }),
240
- );
222
+ }).pipe(Type.makeObject(DXN.make('com.test.type.todoList', '0.1.0')));
241
223
 
242
224
  const todoList = Obj.make(TodoList, { name: 'My Tasks' });
243
225
 
244
226
  // This should work: setting a nested property on an array element.
245
227
  // The required 'id' field should be initialized with a default value.
246
- Obj.change(todoList, (todoList) => Obj.setValue(todoList, ['tasks', 0, 'title'], 'Buy groceries'));
228
+ Obj.update(todoList, (todoList) => Obj.setValue(todoList, ['tasks', 0, 'title'], 'Buy groceries'));
247
229
 
248
230
  expect(todoList.tasks?.[0].id).toBe(''); // Default value for required String
249
231
  expect(todoList.tasks?.[0].title).toBe('Buy groceries');
@@ -261,16 +243,11 @@ describe('Obj.setValue', () => {
261
243
  const Container = Schema.Struct({
262
244
  name: Schema.String,
263
245
  items: Schema.optional(Schema.Array(Item)),
264
- }).pipe(
265
- Type.object({
266
- typename: 'test.com/Container',
267
- version: '0.1.0',
268
- }),
269
- );
246
+ }).pipe(Type.makeObject(DXN.make('com.test.type.container', '0.1.0')));
270
247
 
271
248
  const container = Obj.make(Container, { name: 'box' });
272
249
 
273
- Obj.change(container, (container) => Obj.setValue(container, ['items', 0, 'label'], 'First Item'));
250
+ Obj.update(container, (container) => Obj.setValue(container, ['items', 0, 'label'], 'First Item'));
274
251
 
275
252
  // All required primitive fields should have default values.
276
253
  expect(container.items?.[0].id).toBe('');