@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
@@ -4,19 +4,129 @@
4
4
 
5
5
  import { describe, expect, test } from 'vitest';
6
6
 
7
- import type * as Entity from './Entity';
7
+ import * as Entity from './Entity';
8
8
  import * as Obj from './Obj';
9
9
  import * as Relation from './Relation';
10
10
  import { TestSchema } from './testing';
11
+ import * as Type from './Type';
12
+
13
+ const makeObject = () =>
14
+ Obj.make(TestSchema.Person, {
15
+ name: 'Test',
16
+ username: 'test',
17
+ email: 'test@example.com',
18
+ tasks: [],
19
+ });
20
+
21
+ const makeRelation = (obj: TestSchema.Person) =>
22
+ Relation.make(TestSchema.HasManager, { [Relation.Source]: obj, [Relation.Target]: obj });
11
23
 
12
24
  describe('Entity', () => {
13
25
  test('Entity.Unknown accepts any object or relation', () => {
14
- const obj = Obj.make(TestSchema.Person, { name: 'Test' });
15
- const rel = Relation.make(TestSchema.HasManager, { [Relation.Source]: obj, [Relation.Target]: obj });
16
- const doSomething = (entity: Entity.Unknown) => {
17
- return entity;
18
- };
26
+ const obj = makeObject();
27
+ const rel = makeRelation(obj);
28
+ const doSomething = (entity: Entity.Unknown) => entity;
19
29
  expect(doSomething(obj)).toBe(obj);
20
30
  expect(doSomething(rel)).toBe(rel);
21
31
  });
32
+
33
+ // `isEntity` is a bare brand check (`[KindId] !== undefined`). All three entity
34
+ // kinds — objects, relations, and type entities — carry the brand, so all three
35
+ // are recognised as entities. (Type entities brand with `EntityKind.Type`.)
36
+ describe('isEntity / isSnapshot', () => {
37
+ test('object instance is an entity', () => {
38
+ const obj = makeObject();
39
+ expect(Entity.isEntity(obj)).toBe(true);
40
+ expect(Entity.isSnapshot(obj)).toBe(false);
41
+ });
42
+
43
+ test('relation instance is an entity', () => {
44
+ const rel = makeRelation(makeObject());
45
+ expect(Entity.isEntity(rel)).toBe(true);
46
+ expect(Entity.isSnapshot(rel)).toBe(false);
47
+ });
48
+
49
+ test('type entity is an entity', () => {
50
+ expect(Entity.isEntity(TestSchema.Person)).toBe(true);
51
+ expect(Entity.isSnapshot(TestSchema.Person)).toBe(false);
52
+ });
53
+
54
+ test('non-entities are rejected', () => {
55
+ expect(Entity.isEntity(null)).toBe(false);
56
+ expect(Entity.isEntity({})).toBe(false);
57
+ expect(Entity.isEntity({ id: 'x' })).toBe(false);
58
+ expect(Entity.isEntity('string')).toBe(false);
59
+ });
60
+ });
61
+
62
+ // Object and relation instances behave identically across the Entity.* accessor
63
+ // surface: these accessors are written for runtime instances and read the
64
+ // instance's identity, type pointer and metadata.
65
+ describe.each([
66
+ ['object', () => makeObject(), 'com.example.type.person'],
67
+ ['relation', () => makeRelation(makeObject()), 'com.example.type.hasManager'],
68
+ ] as const)('instance accessors (%s)', (_label, make, typename) => {
69
+ test('getURI returns an echo URI', () => {
70
+ const entity = make();
71
+ expect(Entity.getURI(entity)).toMatch(/^echo:/);
72
+ });
73
+
74
+ test('getTypename returns the typename', () => {
75
+ expect(Entity.getTypename(make())).toBe(typename);
76
+ });
77
+
78
+ test('getTypeURI returns the type DXN', () => {
79
+ expect(Entity.getTypeURI(make())).toBe(`dxn:${typename}:0.1.0`);
80
+ });
81
+
82
+ test('getType resolves back to the type entity', () => {
83
+ const type = Entity.getType(make());
84
+ expect(type).toBeDefined();
85
+ expect(Type.getTypename(type!)).toBe(typename);
86
+ });
87
+
88
+ test('getMeta returns metadata', () => {
89
+ expect(Entity.getMeta(make())).toBeDefined();
90
+ });
91
+
92
+ test('isDeleted is false for a live entity', () => {
93
+ expect(Entity.isDeleted(make())).toBe(false);
94
+ });
95
+
96
+ test('toJSON serializes the entity', () => {
97
+ const json = Entity.toJSON(make());
98
+ expect(json).toMatchObject({ '@type': expect.stringContaining(typename) });
99
+ });
100
+ });
101
+
102
+ // Type entities are first-class entities: the Entity.* accessors work on them too.
103
+ // `getURI`/`getTypename` return the type's OWN identity, while `getType`/`getTypeURI`
104
+ // (which mean "the type this entity is an instance of") resolve to the meta-type
105
+ // `Type.Type`.
106
+ describe('type entity', () => {
107
+ test('isEntity / getMeta / isDeleted', () => {
108
+ expect(Entity.isEntity(TestSchema.Person)).toBe(true);
109
+ expect(Entity.getMeta(TestSchema.Person)).toBeDefined();
110
+ expect(Entity.isDeleted(TestSchema.Person)).toBe(false);
111
+ });
112
+
113
+ test('getURI / getTypename return the type entity’s own identity', () => {
114
+ expect(Entity.getURI(TestSchema.Person)).toBe('dxn:com.example.type.person:0.1.0');
115
+ expect(Entity.getTypename(TestSchema.Person)).toBe('com.example.type.person');
116
+ });
117
+
118
+ test('getType / getTypeURI resolve to the meta-type (Type.Type)', () => {
119
+ expect(Entity.getType(TestSchema.Person)).toBe(Type.Type);
120
+ expect(Entity.getTypeURI(TestSchema.Person)).toBe('dxn:org.dxos.type.schema:0.1.0');
121
+ });
122
+
123
+ test('Entity.* and Type.* agree on type identity', () => {
124
+ expect(Entity.getURI(TestSchema.Person)).toBe(Type.getURI(TestSchema.Person));
125
+ expect(Entity.getTypename(TestSchema.Person)).toBe(Type.getTypename(TestSchema.Person));
126
+ expect(Type.isType(TestSchema.Person)).toBe(true);
127
+ expect(Type.isObject(TestSchema.Person)).toBe(true);
128
+ expect(Type.isRelation(TestSchema.HasManager)).toBe(true);
129
+ expect(Type.getVersion(TestSchema.Person)).toBe('0.1.0');
130
+ });
131
+ });
22
132
  });
package/src/Entity.ts CHANGED
@@ -4,12 +4,17 @@
4
4
 
5
5
  // @import-as-namespace
6
6
 
7
+ import * as Schema from 'effect/Schema';
8
+
7
9
  import type { ForeignKey } from '@dxos/echo-protocol';
8
- import type { DXN, ObjectId } from '@dxos/keys';
10
+ import type { EntityId, URI } from '@dxos/keys';
9
11
 
10
12
  import * as internal from './internal';
13
+ import * as objInternal from './internal/Obj';
14
+ import type * as Ref from './Ref';
11
15
  import type * as Relation from './Relation';
12
- import type * as Type from './Type';
16
+ import type * as Tag from './Tag';
17
+ import * as Type from './Type';
13
18
 
14
19
  // Re-export KindId and SnapshotKindId from internal.
15
20
  export const KindId = internal.KindId;
@@ -31,7 +36,7 @@ export const KindSchema = internal.EntityKindSchema;
31
36
  */
32
37
  export interface OfKind<K extends Kind> {
33
38
  readonly [KindId]: K;
34
- readonly id: ObjectId;
39
+ readonly id: EntityId;
35
40
  }
36
41
 
37
42
  /**
@@ -39,7 +44,7 @@ export interface OfKind<K extends Kind> {
39
44
  */
40
45
  export interface SnapshotOfKind<K extends Kind> {
41
46
  readonly [SnapshotKindId]: K;
42
- readonly id: ObjectId;
47
+ readonly id: EntityId;
43
48
  }
44
49
 
45
50
  /**
@@ -52,6 +57,27 @@ export type Entity<Props> = OfKind<Kind> & Props;
52
57
  */
53
58
  export interface Unknown extends OfKind<Kind> {}
54
59
 
60
+ /**
61
+ * Effect Schema for any ECHO entity (object or relation).
62
+ *
63
+ * Kind-agnostic counterpart to `Obj.Unknown` / `Relation.Unknown` — validates
64
+ * the structural shape (id + properties) without constraining `[KindId]`. Used
65
+ * in operation input schemas that accept any entity flavour (e.g.
66
+ * `Schema.Array(Entity.Unknown)`).
67
+ *
68
+ * The cast bridges the runtime structural schema to the branded `Unknown` type:
69
+ * `[KindId]` is a symbol brand that can't be expressed in a runtime `Struct`,
70
+ * so the entity guarantee is carried at the type level only (same approach as
71
+ * `Obj.Unknown` / `Relation.Unknown`). Unlike those, this is kind-agnostic so it
72
+ * isn't an `UnknownTypeSchema<_, K>` (there's no single `K`) and carries no
73
+ * `TypeAnnotation`.
74
+ */
75
+ export const Unknown: Schema.Schema<Unknown> = Schema.Struct({
76
+ id: Schema.String,
77
+ }).pipe(
78
+ Schema.extend(Schema.Record({ key: Schema.String, value: Schema.Unknown })),
79
+ ) as unknown as Schema.Schema<Unknown>;
80
+
55
81
  /**
56
82
  * Snapshot of an Obj or Relation.
57
83
  * Branded with SnapshotKindId instead of KindId.
@@ -80,12 +106,30 @@ export type Properties<T> = Omit<T, 'id' | KindId | Relation.Source | Relation.T
80
106
  * Check if a value is an ECHO entity (object or relation).
81
107
  * Returns `false` for snapshots.
82
108
  */
83
- export const isEntity = (value: unknown): value is Unknown => {
84
- if (typeof value !== 'object' || value === null) {
85
- return false;
109
+ export const isEntity: (value: unknown) => value is Unknown = internal.isEntity;
110
+
111
+ /**
112
+ * Test if a value is an instance of a given object or relation type.
113
+ *
114
+ * Kind-agnostic counterpart to `Obj.instanceOf` / `Relation.instanceOf` —
115
+ * use this when the caller's input type is `Type.AnyObj | Type.AnyRelation`.
116
+ *
117
+ * @example
118
+ * ```ts
119
+ * // Caller doesn't know whether `type` is object- or relation-kind.
120
+ * const matches = <T extends Type.AnyObj | Type.AnyRelation>(type: T, value: unknown) =>
121
+ * Entity.instanceOf(type, value);
122
+ * ```
123
+ */
124
+ export const instanceOf: {
125
+ <S extends Type.AnyEntity>(schema: S): (value: unknown) => value is Type.InstanceType<S>;
126
+ <S extends Type.AnyEntity>(schema: S, value: unknown): value is Type.InstanceType<S>;
127
+ } = ((...args: [schema: Type.AnyEntity, value?: unknown]) => {
128
+ if (args.length === 1) {
129
+ return (entity: unknown) => internal.isInstanceOf(args[0], entity);
86
130
  }
87
- return (value as any)[KindId] !== undefined;
88
- };
131
+ return internal.isInstanceOf(args[0], args[1]);
132
+ }) as any;
89
133
 
90
134
  /**
91
135
  * Check if a value is an ECHO entity snapshot.
@@ -123,25 +167,60 @@ export type Meta = typeof Meta;
123
167
  export type JSON = internal.ObjectJSON;
124
168
 
125
169
  /**
126
- * Get the DXN of an entity (object or relation).
170
+ * Whether the entity is a type-kind entity (a `Type.Type` produced by
171
+ * `Type.makeObject` / `Type.makeRelation`, or a persisted schema). Type entities
172
+ * carry their identity (typename/version) on themselves rather than referencing a
173
+ * separate type, so the accessors below route them through the `Type.*` module.
174
+ */
175
+ const isTypeEntity = (entity: unknown): boolean => internal.getEntityKindBrand(entity) === internal.EntityKind.Type;
176
+
177
+ /**
178
+ * Any value the read accessors operate on: a reactive entity or a snapshot.
179
+ * Type entities (`Type.AnyEntity`) are also accepted — they're first-class
180
+ * entities, and `Unknown`'s kind-agnostic brand already subsumes them.
127
181
  */
128
- export const getDXN = (entity: Unknown | Snapshot): DXN => internal.getDXN(entity);
182
+ export type AnyInput = Unknown | Snapshot;
129
183
 
130
184
  /**
131
- * Get the DXN of an entity's type.
185
+ * Get the canonical URI of an entity (object, relation, or type). Returns `URI.URI` —
186
+ * an `EID` for object/relation instances and persisted types, or a typename
187
+ * `DXN` for static type entities; narrow with `EID.parse(uri)` or
188
+ * `DXN.tryMake(uri)` at the point of use.
189
+ *
190
+ * @param options.prefer - Controls the URI form (see {@link internal.GetURIOptions}).
132
191
  */
133
- export const getTypeDXN = internal.getTypeDXN;
192
+ export const getURI = (entity: AnyInput, options?: internal.GetURIOptions): URI.URI =>
193
+ isTypeEntity(entity) ? Type.getURI(entity as Type.AnyEntity) : internal.getUri(entity as Unknown, options);
134
194
 
135
195
  /**
136
- * Get the schema of an entity.
137
- * Returns the branded ECHO schema used to create the entity.
196
+ * Get the DXN of an entity's type. For object/relation instances this is the URI
197
+ * of the type they were created from; for a type entity it is the URI of the
198
+ * meta-type ({@link Type.Type}, `dxn:org.dxos.type.schema:0.1.0`).
138
199
  */
139
- export const getSchema: (entity: Unknown | Snapshot) => Type.AnyEntity | undefined = internal.getSchema as any;
200
+ export const getTypeURI = (entity: AnyInput): URI.URI | undefined =>
201
+ isTypeEntity(entity) ? Type.getURI(Type.Type) : internal.getTypeURI(entity as Unknown);
140
202
 
141
203
  /**
142
- * Get the typename of an entity's type.
204
+ * Get the type entity (`Type.AnyEntity`) the instance was created from.
205
+ *
206
+ * Returns `undefined` when the entity's type isn't registered in this runtime
207
+ * (e.g. a freshly deserialized snapshot whose type entity hasn't been wired
208
+ * up yet, or an entity loaded from storage before its schema is known). To
209
+ * get the Effect Schema from the returned entity, use `Type.getSchema(...)`.
210
+ *
211
+ * For a type entity, returns the meta-type {@link Type.Type} (a type entity's
212
+ * type is "Type").
143
213
  */
144
- export const getTypename = (entity: Unknown | Snapshot): string | undefined => internal.getTypename(entity);
214
+ export const getType = (entity: AnyInput): Type.AnyEntity | undefined =>
215
+ isTypeEntity(entity) ? Type.Type : (internal.getType(entity) as Type.AnyEntity | undefined);
216
+
217
+ /**
218
+ * Get the typename of an entity's type. For object/relation instances this is the
219
+ * typename of the type they were created from; for a type entity it is the type's
220
+ * own typename (e.g. `com.example.type.person`).
221
+ */
222
+ export const getTypename = (entity: AnyInput): string | undefined =>
223
+ isTypeEntity(entity) ? Type.getTypename(entity as Type.AnyEntity) : internal.getTypename(entity as Unknown);
145
224
 
146
225
  /**
147
226
  * Get the database an entity belongs to.
@@ -154,9 +233,9 @@ export const getDatabase = (entity: Unknown | Snapshot): any | undefined => inte
154
233
  * Returns read-only meta when passed a regular entity or snapshot.
155
234
  */
156
235
  // TODO(wittjosiah): When passed a Snapshot, should return a snapshot of meta, not the live meta proxy.
157
- export function getMeta(entity: Mutable<Unknown>): internal.ObjectMeta;
236
+ export function getMeta(entity: Mutable<Unknown>): internal.EntityMeta;
158
237
  export function getMeta(entity: Unknown | Snapshot): internal.ReadonlyMeta;
159
- export function getMeta(entity: Unknown | Snapshot | Mutable<Unknown>): internal.ObjectMeta | internal.ReadonlyMeta {
238
+ export function getMeta(entity: Unknown | Snapshot | Mutable<Unknown>): internal.EntityMeta | internal.ReadonlyMeta {
160
239
  return internal.getMetaChecked(entity);
161
240
  }
162
241
 
@@ -172,14 +251,31 @@ export const isDeleted = (entity: Unknown | Snapshot): boolean => internal.isDel
172
251
 
173
252
  /**
174
253
  * Get the label of an entity.
254
+ *
255
+ * @param options.fallback `'typename'` returns the entity's typename when no
256
+ * label is set (e.g. `org.dxos.type.table`).
257
+ */
258
+ export const getLabel = (entity: Unknown | Snapshot, options?: internal.GetLabelOptions): string | undefined =>
259
+ internal.getLabel(entity, options);
260
+
261
+ /**
262
+ * Set the label of an entity.
263
+ * Must be called within an `Entity.update` / `Obj.update` / `Relation.update` callback.
175
264
  */
176
- export const getLabel = (entity: Unknown | Snapshot): string | undefined => internal.getLabel(entity);
265
+ export const setLabel = (entity: Mutable<Unknown>, label: string): void => internal.setLabel(entity, label);
177
266
 
178
267
  /**
179
268
  * Get the description of an entity.
180
269
  */
181
270
  export const getDescription = (entity: Unknown | Snapshot): string | undefined => internal.getDescription(entity);
182
271
 
272
+ /**
273
+ * Get the icon annotation for an entity (object or relation), resolved via its type-level
274
+ * `IconAnnotation`. Returns the full `{ icon, hue }` annotation so callers can use both
275
+ * the phosphor icon name and the suggested colour.
276
+ */
277
+ export const getIcon = (entity: Unknown | Snapshot): internal.IconAnnotation | undefined => internal.getIcon(entity);
278
+
183
279
  /**
184
280
  * Convert an entity to its JSON representation.
185
281
  */
@@ -198,7 +294,7 @@ export const subscribe = (entity: Unknown, callback: () => void): (() => void) =
198
294
  //
199
295
 
200
296
  /**
201
- * Used to provide a mutable view of an entity within `Entity.change`.
297
+ * Used to provide a mutable view of an entity within `Entity.update`.
202
298
  */
203
299
  export type Mutable<T> = internal.Mutable<T>;
204
300
 
@@ -206,7 +302,7 @@ export type Mutable<T> = internal.Mutable<T>;
206
302
  * Perform mutations on an entity (object or relation) within a change context.
207
303
  *
208
304
  * Entities are read-only by default. Mutations are batched and notifications fire
209
- * when the callback completes. Direct mutations outside of `Entity.change` will throw
305
+ * when the callback completes. Direct mutations outside of `Entity.update` will throw
210
306
  * at runtime.
211
307
  *
212
308
  * @param entity - The echo entity (object or relation) to mutate.
@@ -214,30 +310,36 @@ export type Mutable<T> = internal.Mutable<T>;
214
310
  *
215
311
  * @example
216
312
  * ```typescript
217
- * // Mutate within Entity.change
218
- * Entity.change(entity, (obj) => {
313
+ * // Mutate within Entity.update
314
+ * Entity.update(entity, (obj) => {
219
315
  * obj.name = 'Updated';
220
316
  * obj.count = 42;
221
317
  * });
222
318
  *
223
319
  * // Direct mutation throws
224
- * entity.name = 'Bob'; // Error: Cannot modify outside Entity.change()
320
+ * entity.name = 'Bob'; // Error: Cannot modify outside Entity.update()
225
321
  * ```
226
322
  *
227
- * Note: For type-specific operations, prefer `Obj.change` or `Relation.change`.
323
+ * Note: For type-specific operations, prefer `Obj.update` or `Relation.update`.
228
324
  */
229
- export const change = <T extends Unknown>(entity: T, callback: internal.ChangeCallback<T>): void => {
325
+ export const update = <T extends Unknown>(entity: T, callback: internal.ChangeCallback<T>): void => {
230
326
  internal.change(entity, callback);
231
327
  };
232
328
 
233
329
  /**
234
330
  * Add a tag to an entity.
235
- * Must be called within an `Entity.change`, `Obj.change`, or `Relation.change` callback.
331
+ * Must be called within an `Entity.update`, `Obj.update`, or `Relation.update` callback.
236
332
  */
237
- export const addTag = (entity: Mutable<Unknown>, tag: string): void => internal.addTag(entity, tag);
333
+ export const addTag = (entity: Mutable<Unknown>, tag: Ref.Ref<Tag.Tag>): void => internal.addTag(entity, tag);
238
334
 
239
335
  /**
240
336
  * Remove a tag from an entity.
241
- * Must be called within an `Entity.change`, `Obj.change`, or `Relation.change` callback.
337
+ * Must be called within an `Entity.update`, `Obj.update`, or `Relation.update` callback.
242
338
  */
243
- export const removeTag = (entity: Mutable<Unknown>, tag: string): void => internal.removeTag(entity, tag);
339
+ export const removeTag = (entity: Mutable<Unknown>, tag: Ref.Ref<Tag.Tag>): void => internal.removeTag(entity, tag);
340
+
341
+ //
342
+ // Atoms
343
+ //
344
+
345
+ export const atom = objInternal.makeEntity;
package/src/Err.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  // @import-as-namespace
6
6
 
7
7
  import { BaseError, type BaseErrorOptions } from '@dxos/errors';
8
- import { type DXN } from '@dxos/keys';
8
+ import { type URI } from '@dxos/keys';
9
9
 
10
10
  export class SchemaNotFoundError extends BaseError.extend('SchemaNotFoundError', 'Schema not found') {
11
11
  constructor(schema: string, options?: BaseErrorOptions) {
@@ -13,9 +13,9 @@ export class SchemaNotFoundError extends BaseError.extend('SchemaNotFoundError',
13
13
  }
14
14
  }
15
15
 
16
- export class ObjectNotFoundError extends BaseError.extend('ObjectNotFoundError', 'Object not found') {
17
- constructor(dxn: DXN, options?: BaseErrorOptions) {
18
- super({ context: { dxn }, ...options });
16
+ export class EntityNotFoundError extends BaseError.extend('EntityNotFoundError', 'Entity not found') {
17
+ constructor(uri: URI.URI, options?: BaseErrorOptions) {
18
+ super({ context: { uri }, ...options });
19
19
  }
20
20
  }
21
21
 
package/src/Feed.ts CHANGED
@@ -10,7 +10,7 @@ import * as Layer from 'effect/Layer';
10
10
  import type * as Option from 'effect/Option';
11
11
  import * as Schema from 'effect/Schema';
12
12
 
13
- import { DXN, type ObjectId } from '@dxos/keys';
13
+ import { DXN, EID } from '@dxos/keys';
14
14
 
15
15
  import * as Annotation from './Annotation';
16
16
  import type * as Entity from './Entity';
@@ -43,21 +43,15 @@ export const Feed = Schema.Struct({
43
43
  */
44
44
  namespace: Schema.optional(Schema.Literal('data', 'trace')),
45
45
  }).pipe(
46
- Type.object({
47
- typename: 'org.dxos.type.feed',
48
- version: '0.1.0',
49
- }),
50
- internal.SystemTypeAnnotation.set(true),
51
- Annotation.IconAnnotation.set({
52
- icon: 'ph--rows--regular',
53
- hue: 'yellow',
54
- }),
46
+ internal.HiddenAnnotation.set(true),
47
+ Annotation.IconAnnotation.set({ icon: 'ph--rows--regular', hue: 'yellow' }),
48
+ Type.makeObject(DXN.make('org.dxos.type.feed', '0.1.0')),
55
49
  );
56
50
 
57
51
  /**
58
52
  * TypeScript instance type for a Feed object.
59
53
  */
60
- export interface Feed extends Schema.Schema.Type<typeof Feed> {}
54
+ export type Feed = Type.InstanceType<typeof Feed>;
61
55
 
62
56
  //
63
57
  // Types
@@ -80,6 +74,29 @@ export interface RetentionOptions {
80
74
  cursor?: string;
81
75
  }
82
76
 
77
+ /**
78
+ * Sync options for a feed.
79
+ */
80
+ export interface SyncOptions {
81
+ /** Push local changes to the server. Defaults to true. */
82
+ shouldPush?: boolean;
83
+ /** Pull remote changes from the server. Defaults to true. */
84
+ shouldPull?: boolean;
85
+ }
86
+
87
+ /**
88
+ * Queue replication backlog for a feed namespace.
89
+ * `0` / `0` means caught up on pull and push.
90
+ */
91
+ export interface SyncState {
92
+ /** Blocks still to pull from remote. */
93
+ blocksToPull: number;
94
+ /** Unpositioned blocks still to push to remote. */
95
+ blocksToPush: number;
96
+ /** Total blocks stored locally for the feed namespace. */
97
+ totalBlocks: number;
98
+ }
99
+
83
100
  //
84
101
  // Factory
85
102
  //
@@ -96,39 +113,11 @@ export interface RetentionOptions {
96
113
  export const make = (props: Obj.MakeProps<typeof Feed> = {}): Feed => Obj.make(Feed, props);
97
114
 
98
115
  /**
99
- * Derives the queue DXN from the feed object's DXN.
100
- * Returns `undefined` when the feed is not stored in a space yet.
116
+ * Returns the feed object's EID when the feed is stored in a space.
101
117
  *
102
118
  * Used internally by the feed service layer.
103
119
  */
104
- export const getQueueDxn = (feed: Feed): DXN | undefined => {
105
- const self = Obj.getDXN(feed).asEchoDXN();
106
- if (!self || !self.spaceId) {
107
- return undefined;
108
- }
109
- return new DXN(DXN.kind.QUEUE, [feed.namespace ?? 'data', self.spaceId, self.echoId]);
110
- };
111
-
112
- /**
113
- * Creates a Feed object from a queue DXN, inferring the feed's id and namespace from the DXN parts.
114
- *
115
- * The resulting Feed, when added to the same space as the queue, will have a queue DXN
116
- * equal to the input (see `Feed.getQueueDxn`). Useful when migrating `Ref(Queue)` fields to
117
- * `Ref(Feed.Feed)`.
118
- *
119
- * @remarks Unsafe because the caller must ensure the queue DXN's space matches the database
120
- * the feed is added to; the feed id is set from the queue id, bypassing id generation.
121
- */
122
- export const unsafeFromQueueDXN = (queueDxn: DXN): Feed => {
123
- const parts = queueDxn.asQueueDXN();
124
- if (!parts) {
125
- throw new Error(`Expected a queue DXN, got: ${queueDxn.toString()}`);
126
- }
127
- return Obj.make(Feed, {
128
- id: parts.queueId as ObjectId,
129
- namespace: parts.subspaceTag === 'trace' ? 'trace' : undefined,
130
- });
131
- };
120
+ export const getQueueUri = (feed: Feed): EID.EID | undefined => EID.tryParse(Obj.getURI(feed));
132
121
 
133
122
  //
134
123
  // Service
@@ -150,7 +139,6 @@ export class FeedService extends Context.Tag('@dxos/echo/Feed/FeedService')<
150
139
  /**
151
140
  * Removes items from a feed by ID.
152
141
  */
153
- // TODO(dmaretskyi): Change type to ObjectId.
154
142
  remove(feed: Feed, ids: string[]): Promise<void>;
155
143
 
156
144
  /**
@@ -160,6 +148,16 @@ export class FeedService extends Context.Tag('@dxos/echo/Feed/FeedService')<
160
148
  <Q extends Query.Any>(feed: Feed, query: Q): QueryResult.QueryResult<Query.Type<Q>>;
161
149
  <F extends Filter.Any>(feed: Feed, filter: F): QueryResult.QueryResult<Filter.Type<F>>;
162
150
  };
151
+
152
+ /**
153
+ * Syncs the feed with the server.
154
+ */
155
+ sync(feed: Feed, options?: SyncOptions): Promise<void>;
156
+
157
+ /**
158
+ * Returns queue replication backlog for the feed's namespace.
159
+ */
160
+ getSyncState(feed: Feed): Promise<SyncState>;
163
161
  }
164
162
  >() {}
165
163
 
@@ -173,6 +171,21 @@ export type Service = FeedService;
173
171
  */
174
172
  export const Service = FeedService;
175
173
 
174
+ /**
175
+ * Effect context service that holds the current feed for a scoped operation.
176
+ *
177
+ * @deprecated Prefer threading a `Feed.Feed` explicitly through function signatures
178
+ * over hiding it behind a context service.
179
+ */
180
+ export class ContextFeedService extends Context.Tag('@dxos/echo/Feed/ContextFeedService')<
181
+ ContextFeedService,
182
+ {
183
+ readonly feed: Feed;
184
+ }
185
+ >() {
186
+ static layer = (feed: Feed): Layer.Layer<ContextFeedService> => Layer.succeed(ContextFeedService, { feed });
187
+ }
188
+
176
189
  /**
177
190
  * Layer that provides a Feed service that throws when accessed.
178
191
  * Useful as a default layer when no feed service is available.
@@ -187,6 +200,12 @@ export const notAvailable: Layer.Layer<FeedService> = Layer.succeed(FeedService,
187
200
  query: () => {
188
201
  throw new Error('Feed.FeedService not available');
189
202
  },
203
+ sync: () => {
204
+ throw new Error('Feed.FeedService not available');
205
+ },
206
+ getSyncState: () => {
207
+ throw new Error('Feed.FeedService not available');
208
+ },
190
209
  } as Context.Tag.Service<FeedService>);
191
210
 
192
211
  //
@@ -262,6 +281,35 @@ export const runQuery: {
262
281
  } = (feed: Feed, queryOrFilter: Query.Any | Filter.Any) =>
263
282
  query(feed, queryOrFilter as any).pipe(Effect.flatMap((queryResult) => Effect.promise(() => queryResult.run())));
264
283
 
284
+ /**
285
+ * Syncs the feed with the server.
286
+ *
287
+ * @example
288
+ * ```ts
289
+ * yield* Feed.sync(feed);
290
+ * yield* Feed.sync(feed, { shouldPush: false });
291
+ * ```
292
+ */
293
+ export const sync = (feed: Feed, options?: SyncOptions): Effect.Effect<void, never, FeedService> =>
294
+ Effect.gen(function* () {
295
+ const service = yield* FeedService;
296
+ yield* Effect.promise(() => service.sync(feed, options));
297
+ });
298
+
299
+ /**
300
+ * Returns queue replication backlog for the feed's namespace.
301
+ *
302
+ * @example
303
+ * ```ts
304
+ * const { blocksToPull, blocksToPush } = yield* Feed.getSyncState(feed);
305
+ * ```
306
+ */
307
+ export const getSyncState = (feed: Feed): Effect.Effect<SyncState, never, FeedService> =>
308
+ Effect.gen(function* () {
309
+ const service = yield* FeedService;
310
+ return yield* Effect.promise(() => service.getSyncState(feed));
311
+ });
312
+
265
313
  /**
266
314
  * Creates a cursor for iterating over feed items.
267
315
  * Currently stubbed — cursor operations are not yet implemented.
@@ -292,13 +340,13 @@ export const nextOption = <T = Obj.Snapshot>(_cursor: Cursor<T>): Effect.Effect<
292
340
 
293
341
  /**
294
342
  * Sets the local retention policy for a feed.
295
- * Currently stubbed — queues do not yet support retention.
343
+ * Currently stubbed — feeds do not yet support retention.
296
344
  *
297
345
  * @example
298
346
  * ```ts
299
347
  * yield* Feed.setRetention(feed, { count: 1000 });
300
348
  * ```
301
349
  */
302
- // TODO(feed): Implement when queue retention is supported.
350
+ // TODO(dmaretskyi): Implement when feed retention is supported.
303
351
  export const setRetention = (_feed: Feed, _options: RetentionOptions): Effect.Effect<void, never, FeedService> =>
304
352
  Effect.void;