@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
package/src/Query.ts CHANGED
@@ -8,6 +8,7 @@ import type * as EffectArray from 'effect/Array';
8
8
  import type * as Schema from 'effect/Schema';
9
9
 
10
10
  import { type QueryAST } from '@dxos/echo-protocol';
11
+ import { type URI } from '@dxos/keys';
11
12
 
12
13
  import type * as Collection from './Collection';
13
14
  import * as Database from './Database';
@@ -19,6 +20,8 @@ import * as Obj from './Obj';
19
20
  import type * as Order from './Order';
20
21
  import type * as Ref from './Ref';
21
22
  import type * as Relation from './Relation';
23
+ // eslint-disable-next-line @dxos/rules/import-as-namespace
24
+ import type * as Type$ from './Type';
22
25
  import type * as View from './View';
23
26
 
24
27
  // TODO(dmaretskyi): Split up into interfaces for objects and relations so they can have separate verbs.
@@ -31,6 +34,17 @@ import type * as View from './View';
31
34
  // TODO(dmaretskyi): Filter only properties that are references (or optional references, or unions that include references).
32
35
  type RefPropKey<T> = keyof T & string;
33
36
 
37
+ type RefArrayElement<A> = A extends readonly (infer E)[] ? E : A extends (infer E)[] ? E : never;
38
+
39
+ /** Target entity when traversing an outgoing ref or array-of-refs property. */
40
+ type ReferenceTraversalTarget<P> = P extends Ref.Unknown
41
+ ? Ref.Target<P>
42
+ : P extends Ref.Unknown | undefined
43
+ ? Ref.Target<Exclude<P, undefined>>
44
+ : RefArrayElement<P> extends Ref.Unknown
45
+ ? Ref.Target<RefArrayElement<P>>
46
+ : never;
47
+
34
48
  // TODO(burdon): Narrow T to Entity.Unknown?
35
49
  export interface Query<T> {
36
50
  // TODO(dmaretskyi): See new effect-schema approach to variance.
@@ -51,15 +65,7 @@ export interface Query<T> {
51
65
  * @param key - Property path inside T that is a reference or optional reference.
52
66
  * @returns Query for the target of the reference.
53
67
  */
54
- 'reference'<K extends RefPropKey<T>>(
55
- key: K,
56
- ): Query<
57
- T[K] extends Ref.Unknown
58
- ? Ref.Target<T[K]>
59
- : T[K] extends Ref.Unknown | undefined
60
- ? Ref.Target<Exclude<T[K], undefined>>
61
- : never
62
- >;
68
+ 'reference'<K extends RefPropKey<T>>(key: K): Query<ReferenceTraversalTarget<T[K]>>;
63
69
 
64
70
  /**
65
71
  * Find objects referencing this object.
@@ -69,11 +75,11 @@ export interface Query<T> {
69
75
  */
70
76
  // TODO(dmaretskyi): any way to enforce `Ref.Target<Schema.Schema.Type<S>[key]> == T`?
71
77
  // TODO(dmaretskyi): Ability to go through arrays of references.
72
- 'referencedBy'<S extends Schema.Schema.All>(
73
- target: S | string,
74
- key: RefPropKey<Schema.Schema.Type<S>>,
75
- ): Query<Schema.Schema.Type<S>>;
76
- 'referencedBy'<S extends Schema.Schema.All>(target: S | string): Query<Schema.Schema.Type<S>>;
78
+ 'referencedBy'<S extends Type$.AnyEntity>(
79
+ target: S | URI.URI,
80
+ key: RefPropKey<Type$.InstanceType<S>>,
81
+ ): Query<Type$.InstanceType<S>>;
82
+ 'referencedBy'<S extends Type$.AnyEntity>(target: S | URI.URI): Query<Type$.InstanceType<S>>;
77
83
  'referencedBy'(): Query<any>;
78
84
 
79
85
  /**
@@ -82,21 +88,21 @@ export interface Query<T> {
82
88
  * @param relation - Schema of the relation.
83
89
  * @param predicates - Predicates to filter the relation objects.
84
90
  */
85
- 'sourceOf'<S extends Schema.Schema.All>(
86
- relation?: S | string,
87
- predicates?: Filter.Props<Schema.Schema.Type<S>>,
88
- ): Query<Schema.Schema.Type<S>>;
91
+ 'sourceOf'<R extends Type$.AnyRelation>(
92
+ relation?: R | URI.URI,
93
+ predicates?: Filter.Props<Type$.InstanceType<R>>,
94
+ ): Query<Type$.InstanceType<R>>;
89
95
 
90
96
  /**
91
97
  * Find relations where this object is the target.
92
98
  * @returns Query for the relation objects.
93
- * @param relation - Schema of the relation.
99
+ * @param relation - Type entity of the relation.
94
100
  * @param predicates - Predicates to filter the relation objects.
95
101
  */
96
- 'targetOf'<S extends Schema.Schema.All>(
97
- relation?: S | string,
98
- predicates?: Filter.Props<Schema.Schema.Type<S>>,
99
- ): Query<Schema.Schema.Type<S>>;
102
+ 'targetOf'<R extends Type$.AnyRelation>(
103
+ relation?: R | URI.URI,
104
+ predicates?: Filter.Props<Type$.InstanceType<R>>,
105
+ ): Query<Type$.InstanceType<R>>;
100
106
 
101
107
  /**
102
108
  * For a query for relations, get the source objects.
@@ -199,14 +205,30 @@ export interface Query<T> {
199
205
  'from'(query: Any): Query<T>;
200
206
 
201
207
  /**
202
- * Query from a raw scope specification.
208
+ * Query from one or more raw scopes.
209
+ *
210
+ * Use the {@link Scope} constructors rather than raw tagged objects:
211
+ *
212
+ * ```ts
213
+ * Query.select(Filter.type(Type.Type)).from(Scope.space(), Scope.registry());
214
+ * ```
215
+ */
216
+ 'from'(...scopes: QueryAST.Scope[]): Query<T>;
217
+
218
+ /**
219
+ * Query from a raw scope or array of scopes.
203
220
  */
204
- 'from'(scope: QueryAST.Scope): Query<T>;
221
+ 'from'(scope: QueryAST.Scope | QueryAST.Scope[]): Query<T>;
205
222
 
206
223
  /**
207
224
  * Add options to a query.
208
225
  */
209
226
  'options'(options: QueryAST.QueryOptions): Query<T>;
227
+
228
+ /**
229
+ * Attach a diagnostic label for logs and tooling (execution semantics unchanged).
230
+ */
231
+ 'debugLabel'(label: string): Query<T>;
210
232
  }
211
233
 
212
234
  export type Any = Query<any>;
@@ -244,17 +266,17 @@ class QueryClass implements Any {
244
266
  });
245
267
  }
246
268
 
247
- referencedBy(target?: Schema.Schema.All | string, key?: string): Any {
248
- const dxn = target !== undefined ? internal.getTypeDXNFromSpecifier(target) : null;
269
+ referencedBy(target?: Type$.AnyEntity | URI.URI, key?: string): Any {
270
+ const uri = target !== undefined ? internal.getTypeURIFromSpecifier(target) : null;
249
271
  return new QueryClass({
250
272
  type: 'incoming-references',
251
273
  anchor: this.ast,
252
274
  property: key ?? null,
253
- typename: dxn?.toString() ?? null,
275
+ typename: uri ?? null,
254
276
  });
255
277
  }
256
278
 
257
- sourceOf(relation?: Schema.Schema.All | string, predicates?: Filter.Props<unknown> | undefined): Any {
279
+ sourceOf(relation?: Type$.AnyRelation | URI.URI, predicates?: Filter.Props<unknown> | undefined): Any {
258
280
  return new QueryClass({
259
281
  type: 'relation',
260
282
  anchor: this.ast,
@@ -263,7 +285,7 @@ class QueryClass implements Any {
263
285
  });
264
286
  }
265
287
 
266
- targetOf(relation?: Schema.Schema.All | string, predicates?: Filter.Props<unknown> | undefined): Any {
288
+ targetOf(relation?: Type$.AnyRelation | URI.URI, predicates?: Filter.Props<unknown> | undefined): Any {
267
289
  return new QueryClass({
268
290
  type: 'relation',
269
291
  anchor: this.ast,
@@ -321,18 +343,48 @@ class QueryClass implements Any {
321
343
  }
322
344
 
323
345
  from(
324
- arg:
325
- | Database.Database
326
- | Database.Database[]
327
- | Feed.Feed
328
- | Feed.Feed[]
329
- | Collection.Collection
330
- | View.View
331
- | Any
332
- | QueryAST.Scope
333
- | 'all-accessible-spaces',
334
- options?: { includeFeeds?: boolean },
346
+ ...args:
347
+ | [
348
+ (
349
+ | Database.Database
350
+ | Database.Database[]
351
+ | Feed.Feed
352
+ | Feed.Feed[]
353
+ | Collection.Collection
354
+ | View.View
355
+ | Any
356
+ | QueryAST.Scope
357
+ | QueryAST.Scope[]
358
+ | 'all-accessible-spaces'
359
+ ),
360
+ { includeFeeds?: boolean }?,
361
+ ]
362
+ | QueryAST.Scope[]
335
363
  ): Any {
364
+ // Variadic raw scopes: `.from(Scope.space(), Scope.registry())`.
365
+ if (args.length > 1 && args.every(_isRawScope)) {
366
+ return new QueryClass({
367
+ type: 'from',
368
+ query: this.ast,
369
+ from: { _tag: 'scope', scopes: args as QueryAST.Scope[] },
370
+ });
371
+ }
372
+
373
+ const [arg, options] = args as [
374
+ (
375
+ | Database.Database
376
+ | Database.Database[]
377
+ | Feed.Feed
378
+ | Feed.Feed[]
379
+ | Collection.Collection
380
+ | View.View
381
+ | Any
382
+ | QueryAST.Scope
383
+ | QueryAST.Scope[]
384
+ | 'all-accessible-spaces'
385
+ ),
386
+ { includeFeeds?: boolean }?,
387
+ ];
336
388
  if (arg == null) {
337
389
  throw new TypeError(
338
390
  'Query.from() requires a valid data source argument (database, feed, query, scope, or "all-accessible-spaces").',
@@ -351,20 +403,23 @@ class QueryClass implements Any {
351
403
  return new QueryClass({
352
404
  type: 'from',
353
405
  query: this.ast,
354
- from: {
355
- _tag: 'scope',
356
- scope: {
357
- ...(options?.includeFeeds ? { allQueuesFromSpaces: true } : {}),
358
- },
359
- },
406
+ from: { _tag: 'scope', scopes: [] },
360
407
  });
361
408
  }
362
409
 
363
- if (_isScope(arg)) {
410
+ // Raw scope(s): tagged union objects with _tag 'space' | 'feed' | 'registry'.
411
+ if (Array.isArray(arg) && arg.every(_isRawScope)) {
412
+ return new QueryClass({
413
+ type: 'from',
414
+ query: this.ast,
415
+ from: { _tag: 'scope', scopes: arg as QueryAST.Scope[] },
416
+ });
417
+ }
418
+ if (_isRawScope(arg)) {
364
419
  return new QueryClass({
365
420
  type: 'from',
366
421
  query: this.ast,
367
- from: { _tag: 'scope', scope: arg },
422
+ from: { _tag: 'scope', scopes: [arg] },
368
423
  });
369
424
  }
370
425
 
@@ -377,10 +432,11 @@ class QueryClass implements Any {
377
432
  query: this.ast,
378
433
  from: {
379
434
  _tag: 'scope',
380
- scope: {
381
- spaceIds: databases.map((db) => db.spaceId),
382
- ...(options?.includeFeeds ? { allQueuesFromSpaces: true } : {}),
383
- },
435
+ scopes: databases.map((db) => ({
436
+ _tag: 'space' as const,
437
+ spaceId: db.spaceId,
438
+ ...(options?.includeFeeds ? { includeAllFeeds: true } : {}),
439
+ })),
384
440
  },
385
441
  });
386
442
  }
@@ -405,20 +461,20 @@ class QueryClass implements Any {
405
461
  }
406
462
  }
407
463
 
408
- const feeds = items as Feed.Feed[];
409
- const queueDxns = feeds.flatMap((feed) => {
410
- const dxn = Feed.getQueueDxn(feed);
411
- return dxn ? [dxn.toString()] : [];
464
+ const feedItems = items as Feed.Feed[];
465
+ const feedScopes = feedItems.map((feed) => {
466
+ const uri = Feed.getQueueUri(feed);
467
+ if (!uri) {
468
+ throw new TypeError(
469
+ `Query.from() expects persisted Feed objects with a queue URI; got feed without a space (id=${Obj.getURI(feed)}).`,
470
+ );
471
+ }
472
+ return { _tag: 'feed' as const, feedUri: String(uri) };
412
473
  });
413
474
  return new QueryClass({
414
475
  type: 'from',
415
476
  query: this.ast,
416
- from: {
417
- _tag: 'scope',
418
- scope: {
419
- queues: queueDxns,
420
- },
421
- },
477
+ from: { _tag: 'scope', scopes: feedScopes },
422
478
  });
423
479
  }
424
480
 
@@ -429,6 +485,21 @@ class QueryClass implements Any {
429
485
  options,
430
486
  });
431
487
  }
488
+
489
+ debugLabel(label: string): Any {
490
+ if (this.ast.type === 'options') {
491
+ return new QueryClass({
492
+ type: 'options',
493
+ query: this.ast.query,
494
+ options: { ...this.ast.options, debugLabel: label },
495
+ });
496
+ }
497
+ return new QueryClass({
498
+ type: 'options',
499
+ query: this.ast,
500
+ options: { debugLabel: label },
501
+ });
502
+ }
432
503
  }
433
504
 
434
505
  export const is = (value: unknown): value is Any => {
@@ -461,15 +532,21 @@ export const select = <F extends Filter.Any>(filter: F): Query<Filter.Type<F>> =
461
532
  * Shorthand for: `Query.select(Filter.type(schema, predicates))`.
462
533
  */
463
534
  export const type: {
464
- <S extends Schema.Schema.All>(
535
+ <T extends Type$.AnyEntity>(type: T, predicates?: Filter.Props<Type$.InstanceType<T>>): Query<Type$.InstanceType<T>>;
536
+ // Brand-narrowed schema overload — only well-known unknown schemas pass.
537
+ <S extends internal.UnknownTypeSchema<any, any>>(
465
538
  schema: S,
466
539
  predicates?: Filter.Props<Schema.Schema.Type<S>>,
467
540
  ): Query<Schema.Schema.Type<S>>;
468
- (schema: string, predicates?: Filter.Props<unknown>): Query<any>;
469
- } = (schema: Schema.Schema.All | string, predicates?: Filter.Props<unknown>): Any => {
541
+ <S extends Schema.Union<readonly Schema.Schema.AnyNoContext[]>>(
542
+ union: S,
543
+ predicates?: Filter.Props<Schema.Schema.Type<S>>,
544
+ ): Query<Schema.Schema.Type<S>>;
545
+ (uri: URI.URI, predicates?: Filter.Props<unknown>): Query<any>;
546
+ } = (type: Type$.AnyEntity | URI.URI, predicates?: Filter.Props<unknown>): Any => {
470
547
  return new QueryClass({
471
548
  type: 'select',
472
- filter: Filter.type(schema, predicates).ast,
549
+ filter: Filter.type(type, predicates).ast,
473
550
  });
474
551
  };
475
552
 
@@ -513,32 +590,42 @@ export const without = <T>(source: Query<T>, exclude: Query<T>): Query<T> => {
513
590
  * @returns Query scoped to the given source.
514
591
  */
515
592
  export const from = (
516
- source:
517
- | Database.Database
518
- | Database.Database[]
519
- | Feed.Feed
520
- | Feed.Feed[]
521
- | Any
522
- | QueryAST.Scope
523
- | 'all-accessible-spaces',
524
- options?: { includeFeeds?: boolean },
593
+ ...args:
594
+ | [
595
+ (
596
+ | Database.Database
597
+ | Database.Database[]
598
+ | Feed.Feed
599
+ | Feed.Feed[]
600
+ | Any
601
+ | QueryAST.Scope
602
+ | QueryAST.Scope[]
603
+ | 'all-accessible-spaces'
604
+ ),
605
+ { includeFeeds?: boolean }?,
606
+ ]
607
+ | QueryAST.Scope[]
525
608
  ): Any => {
526
609
  const baseQuery: QueryAST.Query = {
527
610
  type: 'select',
528
611
  filter: Filter.everything().ast,
529
612
  };
530
613
  const wrapper = new QueryClass(baseQuery);
531
- return wrapper.from(source as any, options);
614
+ return (wrapper.from as (...args: unknown[]) => Any)(...args);
532
615
  };
533
616
 
534
- const SCOPE_KEYS = new Set(['spaceIds', 'queues', 'allQueuesFromSpaces']);
535
-
536
- /** Detect a raw Scope object (plain object with only Scope-valid keys). */
537
- const _isScope = (value: unknown): value is QueryAST.Scope => {
538
- if (typeof value !== 'object' || value === null || Array.isArray(value)) {
539
- return false;
540
- }
541
- return Object.keys(value).every((key) => SCOPE_KEYS.has(key));
617
+ const SCOPE_TAGS = new Set<string>(['space', 'feed', 'registry']);
618
+
619
+ /** Detect a raw Scope tagged-union object. */
620
+ const _isRawScope = (value: unknown): value is QueryAST.Scope => {
621
+ return (
622
+ typeof value === 'object' &&
623
+ value !== null &&
624
+ !Array.isArray(value) &&
625
+ '_tag' in value &&
626
+ typeof value._tag === 'string' &&
627
+ SCOPE_TAGS.has(value._tag)
628
+ );
542
629
  };
543
630
 
544
631
  /**
@@ -2,6 +2,10 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import type * as Atom from '@effect-atom/atom/Atom';
6
+ import * as Effect from 'effect/Effect';
7
+ import * as Option from 'effect/Option';
8
+
5
9
  import { type CleanupFn } from '@dxos/async';
6
10
 
7
11
  import type * as Entity from './Entity';
@@ -103,4 +107,26 @@ export interface QueryResult<T> {
103
107
  * Subscribes to changes in query results.
104
108
  */
105
109
  subscribe(callback?: (query: QueryResult<T>) => void, opts?: SubscriptionOptions): CleanupFn;
110
+
111
+ /**
112
+ * Self-updating atom. Updates automatically when query results change.
113
+ *
114
+ * Memoized per QueryResult instance — repeated accesses on the same instance return the same
115
+ * Atom. Safe only when the QueryResult is itself held stable across re-renders (e.g. behind a
116
+ * `useMemo`). It must NOT be used in graph-builder connectors/actions or other atom computes,
117
+ * where `db.query(...)` is called fresh on each re-evaluation: every run constructs a new
118
+ * QueryResult and so a new atom + subscription, leaking the previous ones. Use the memoized
119
+ * {@link atom} family there instead.
120
+ */
121
+ readonly atom: Atom.Atom<T[]>;
122
+ }
123
+
124
+ /**
125
+ * Effect that returns a QueryResult when evaluated, but also has shorthand methods for running the query or getting the first result.
126
+ */
127
+ export interface QueryResultEffect<T, E, R> extends Effect.Effect<QueryResult<T>, E, R> {
128
+ run: Effect.Effect<T[], E, R>;
129
+ first: Effect.Effect<Option.Option<T>, E, R>;
130
+
131
+ // TODO(dmaretskyi): Considering adding `atom`, but since `Database.query` is used in imperative code only, I dont think it will be useful.
106
132
  }
package/src/Ref.ts CHANGED
@@ -8,10 +8,15 @@ import * as Option from 'effect/Option';
8
8
  import type * as Schema from 'effect/Schema';
9
9
  import * as SchemaAST from 'effect/SchemaAST';
10
10
 
11
+ import { type URI } from '@dxos/keys';
12
+
11
13
  import type * as Entity from './Entity';
14
+ import type * as internal from './internal';
12
15
  import * as refInternal from './internal/Ref';
13
16
  import type * as JsonSchema from './JsonSchema';
14
17
  import type * as Obj from './Obj';
18
+ // eslint-disable-next-line @dxos/rules/import-as-namespace
19
+ import type * as TypeNs from './Type';
15
20
 
16
21
  /**
17
22
  * Instance type for a reference.
@@ -42,10 +47,21 @@ export type Unknown = refInternal.Ref<Obj.Unknown>;
42
47
  * ```ts
43
48
  * const Task = Schema.Struct({
44
49
  * assignee: Ref.Ref(Person), // Creates a Ref schema
45
- * }).pipe(Type.object({ typename: 'Task', version: '0.1.0' }));
50
+ * }).pipe(Type.makeObject(DXN.make('com.example.type.task', '0.1.0')));
46
51
  * ```
47
52
  */
48
- export const Ref: <S extends Schema.Schema.Any>(schema: S) => RefSchema<Schema.Schema.Type<S>> = refInternal.Ref;
53
+ export const Ref: {
54
+ <S extends TypeNs.AnyObj | TypeNs.AnyRelation>(type: S): RefSchema<TypeNs.InstanceType<S> & Obj.Unknown>;
55
+
56
+ // `Type.Type` entities (the meta-schema kind) can be referenced too — e.g. a
57
+ // trigger that points to a stored function/workflow definition.
58
+ <T extends TypeNs.Type<any>>(type: T): RefSchema<TypeNs.InstanceType<T>>;
59
+
60
+ // Schema-side overload for the well-known "any object" / "any relation" schemas.
61
+ // Other raw `Schema.Schema` values are intentionally rejected — callers should
62
+ // pass a `Type.Type` entity instead.
63
+ <S extends internal.UnknownTypeSchema<any, any>>(schema: S): RefSchema<Schema.Schema.Type<S> & Obj.Unknown>;
64
+ } = refInternal.Ref as any;
49
65
 
50
66
  export const Array = refInternal.RefArray;
51
67
 
@@ -82,8 +98,10 @@ export const isRef: (value: unknown) => value is Unknown = refInternal.Ref.isRef
82
98
 
83
99
  export const make = refInternal.Ref.make;
84
100
 
85
- // TODO(dmaretskyi): Consider just allowing `make` to accept DXN.
86
- export const fromDXN = refInternal.Ref.fromDXN;
101
+ // TODO(dmaretskyi): Consider just allowing `make` to accept URI.
102
+ export const fromURI = (uri: URI.URI): refInternal.Ref<any> => refInternal.Ref.fromURI(uri);
103
+
104
+ export const hasEntityId = refInternal.Ref.hasEntityId;
87
105
 
88
106
  // TODO(wittjosiah): Factor out?
89
107
  export const isRefType = (ast: SchemaAST.AST): boolean => {
@@ -0,0 +1,155 @@
1
+ // Copyright 2026 DXOS.org
2
+
3
+ // @import-as-namespace
4
+
5
+ import * as Context from 'effect/Context';
6
+ import * as Effect from 'effect/Effect';
7
+
8
+ import { type ReadOnlyEvent } from '@dxos/async';
9
+
10
+ import type * as Database from './Database';
11
+ import * as Entity from './Entity';
12
+ import type * as Filter from './Filter';
13
+ import type * as Query from './Query';
14
+
15
+ /**
16
+ * Identifier denoting an ECHO Registry.
17
+ */
18
+ export const TypeId = Symbol.for('@dxos/echo/Registry');
19
+ export type TypeId = typeof TypeId;
20
+
21
+ /**
22
+ * Composable, in-memory registry of keyed ECHO entities.
23
+ *
24
+ * Entities are stored by id and queried via the standard ECHO Query API.
25
+ * A registry may delegate to an optional upstream registry: results from the local
26
+ * registry take precedence and upstream results fill in anything not found locally.
27
+ *
28
+ * Intended use cases include caches of schemas, operations, blueprints, routines, plugins,
29
+ * etc., sourced from 3rd-party plugins, local code, or local space objects.
30
+ *
31
+ * Types (schema-definition entities produced by `Type.makeObject` / `Type.makeRelation`) are
32
+ * stored the same way as any other entity — via `add()`. Use `list().filter(Type.isType)` to
33
+ * retrieve them.
34
+ *
35
+ * Scope: a Registry is independent of any ECHO space or Hypergraph — it is a process-local,
36
+ * in-memory cache. Wire one per space (e.g. as a Layer scoped to the space's Effect runtime)
37
+ * or share a single instance across spaces depending on the use case.
38
+ *
39
+ * The concrete implementation (and the `makeRegistry` / `registryLayer` factories) lives in
40
+ * `@dxos/echo-client`; this module declares only the interface so that the `@dxos/echo` API surface
41
+ * stays free of query-matching dependencies.
42
+ */
43
+ export interface Registry {
44
+ readonly [TypeId]: TypeId;
45
+
46
+ /**
47
+ * Stable per-instance identifier. Used to key process-local resources (e.g. memoized
48
+ * reactive atoms) to a specific registry instance, analogous to {@link Database.spaceId}.
49
+ */
50
+ readonly id: string;
51
+
52
+ /**
53
+ * Fires whenever local registry contents change (add, remove, or clear).
54
+ */
55
+ readonly changed: ReadOnlyEvent<void>;
56
+
57
+ /**
58
+ * All locally-stored entities.
59
+ * Does not include upstream entities — use {@link list} for that.
60
+ */
61
+ readonly local: readonly Entity.Unknown[];
62
+
63
+ /**
64
+ * Add or replace one or more entities in the local registry.
65
+ * Existing entries with the same id are replaced.
66
+ * Also indexes type entities by DXN for fast lookup.
67
+ */
68
+ add(entities: readonly Entity.Unknown[]): void;
69
+
70
+ /**
71
+ * Remove an entity by id from the local registry.
72
+ * @returns true if an entity was removed, false if it was not found.
73
+ */
74
+ remove(id: string): boolean;
75
+
76
+ /**
77
+ * Remove all locally-stored entities.
78
+ * Does not affect the upstream registry.
79
+ */
80
+ clear(): void;
81
+
82
+ /**
83
+ * Get an entity by id.
84
+ * Searches the local registry first, then falls back to the upstream registry.
85
+ */
86
+ get(id: string): Entity.Unknown | undefined;
87
+
88
+ /**
89
+ * Get an entity by one of its addressing URIs — a type entity by its typename DXN (or, when
90
+ * persisted, its identifier EID), a keyed entity by its `dxn:<key>[:<version>]`. Accepts legacy
91
+ * DXN forms (normalized internally). Searches the local registry first, then falls back to the
92
+ * upstream registry. Narrow the result with `Type.isType` when a type entity is required.
93
+ */
94
+ getByURI(uri: string): Entity.Unknown | undefined;
95
+
96
+ /**
97
+ * List all entities.
98
+ * Local entities take precedence over upstream entities with the same id.
99
+ */
100
+ list(): Entity.Unknown[];
101
+
102
+ /**
103
+ * Run an ECHO query against the registry's entities (implements {@link Database.Queryable}).
104
+ *
105
+ * Matching happens in-memory over {@link list}. Scope (`from`) clauses are unwrapped and
106
+ * ignored — a direct registry query always targets the registry's own entities. The primary
107
+ * way to query registry contents is still through the database (`db.query(...).from(Scope.registry())`),
108
+ * which fans the database and registry together; this method is for querying a registry directly.
109
+ *
110
+ * Only locally-evaluable AST nodes are supported: `select`, `filter`, `limit`, `from`, `options`,
111
+ * and boolean combinators. Server-side concerns (order, traversal, text/timestamp filters) throw.
112
+ */
113
+ query: Database.QueryFn;
114
+ }
115
+
116
+ /**
117
+ * Type guard for {@link Registry}.
118
+ */
119
+ export const isRegistry = (obj: unknown): obj is Registry =>
120
+ obj != null && typeof obj === 'object' && TypeId in obj && (obj as { [TypeId]?: unknown })[TypeId] === TypeId;
121
+
122
+ /**
123
+ * Options for the registry factory (`makeRegistry` in `@dxos/echo-client`).
124
+ */
125
+ export type Options = {
126
+ /**
127
+ * Optional upstream registry. Queries fall back to upstream when an entity
128
+ * is not present in the local registry.
129
+ */
130
+ upstream?: Registry;
131
+
132
+ /**
133
+ * Initial set of entities to seed the local registry with.
134
+ */
135
+ initial?: readonly Entity.Unknown[];
136
+ };
137
+
138
+ /**
139
+ * Effect Context tag for {@link Registry}.
140
+ * Use this to inject a registry into Effect-based code.
141
+ */
142
+ export class Service extends Context.Tag('@dxos/echo/Registry/Service')<Service, Registry>() {}
143
+
144
+ /**
145
+ * Executes a query against the registry and returns the results.
146
+ * Analogous to {@link Database.query} `.run` for the in-process registry.
147
+ */
148
+ export const runQuery: {
149
+ <Q extends Query.Any>(query: Q): Effect.Effect<Query.Type<Q>[], never, Service>;
150
+ <F extends Filter.Any>(filter: F): Effect.Effect<Filter.Type<F>[], never, Service>;
151
+ } = (queryOrFilter: Query.Any | Filter.Any) =>
152
+ Effect.gen(function* () {
153
+ const registry = yield* Service;
154
+ return (yield* Effect.promise(() => registry.query(queryOrFilter as any).run())) as any;
155
+ });