@dxos/echo 0.8.4-main.40e3dcdf1b → 0.8.4-main.43cb759274

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 (428) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +7 -7
  3. package/dist/lib/neutral/Annotation.mjs +29 -6
  4. package/dist/lib/neutral/Database.mjs +8 -9
  5. package/dist/lib/neutral/Entity.mjs +29 -18
  6. package/dist/lib/neutral/Err.mjs +3 -3
  7. package/dist/lib/neutral/Feed.mjs +27 -19
  8. package/dist/lib/neutral/Filter.mjs +25 -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 +18 -0
  13. package/dist/lib/neutral/Obj.mjs +25 -19
  14. package/dist/lib/neutral/Order.mjs +1 -1
  15. package/dist/lib/neutral/Query.mjs +19 -16
  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/Registry.mjs.map +7 -0
  20. package/dist/lib/neutral/Relation.mjs +26 -24
  21. package/dist/lib/neutral/Scope.mjs +12 -0
  22. package/dist/lib/neutral/Scope.mjs.map +7 -0
  23. package/dist/lib/neutral/Tag.mjs +17 -13
  24. package/dist/lib/neutral/Type.mjs +52 -26
  25. package/dist/lib/neutral/chunk-3DKP2EIN.mjs +31 -0
  26. package/dist/lib/neutral/chunk-3DKP2EIN.mjs.map +7 -0
  27. package/dist/lib/neutral/chunk-4BB4MFCN.mjs +154 -0
  28. package/dist/lib/neutral/chunk-4BB4MFCN.mjs.map +7 -0
  29. package/dist/lib/neutral/{chunk-CIRHIEMW.mjs → chunk-4SFPZJVA.mjs} +92 -112
  30. package/dist/lib/neutral/chunk-4SFPZJVA.mjs.map +7 -0
  31. package/dist/lib/neutral/{chunk-YWXWXIE5.mjs → chunk-4Z6GET2X.mjs} +3 -3
  32. package/dist/lib/neutral/chunk-4Z6GET2X.mjs.map +7 -0
  33. package/dist/lib/neutral/{chunk-ANHVGJI4.mjs → chunk-7LOUAPYZ.mjs} +9 -5
  34. package/dist/lib/neutral/chunk-7LOUAPYZ.mjs.map +7 -0
  35. package/dist/lib/neutral/{chunk-43Y5DOS6.mjs → chunk-7OAFN3OX.mjs} +75 -112
  36. package/dist/lib/neutral/chunk-7OAFN3OX.mjs.map +7 -0
  37. package/dist/lib/neutral/{chunk-BOZZPUXE.mjs → chunk-7PRCIDHH.mjs} +41 -81
  38. package/dist/lib/neutral/chunk-7PRCIDHH.mjs.map +7 -0
  39. package/dist/lib/neutral/{chunk-UBEZSGXY.mjs → chunk-BBFJWWAV.mjs} +6 -6
  40. package/dist/lib/neutral/chunk-BBFJWWAV.mjs.map +7 -0
  41. package/dist/lib/neutral/chunk-BDQGMDIX.mjs +132 -0
  42. package/dist/lib/neutral/chunk-BDQGMDIX.mjs.map +7 -0
  43. package/dist/lib/neutral/chunk-CGTI5MXO.mjs +36 -0
  44. package/dist/lib/neutral/chunk-CGTI5MXO.mjs.map +7 -0
  45. package/dist/lib/neutral/{chunk-OMUPQMLR.mjs → chunk-DKLUHO4T.mjs} +1 -1
  46. package/dist/lib/neutral/chunk-DKLUHO4T.mjs.map +7 -0
  47. package/dist/lib/neutral/chunk-DMN2CKPX.mjs +93 -0
  48. package/dist/lib/neutral/chunk-DMN2CKPX.mjs.map +7 -0
  49. package/dist/lib/neutral/{chunk-UTBRYVQC.mjs → chunk-G6CFWUYH.mjs} +2 -2
  50. package/dist/lib/neutral/chunk-H26LSXVJ.mjs +653 -0
  51. package/dist/lib/neutral/chunk-H26LSXVJ.mjs.map +7 -0
  52. package/dist/lib/neutral/{chunk-FXEG7EOK.mjs → chunk-J3MNM65T.mjs} +9 -6
  53. package/dist/lib/neutral/chunk-J3MNM65T.mjs.map +7 -0
  54. package/dist/lib/neutral/chunk-JE7AOSWF.mjs +247 -0
  55. package/dist/lib/neutral/chunk-JE7AOSWF.mjs.map +7 -0
  56. package/dist/lib/neutral/chunk-LAF3LSWI.mjs +379 -0
  57. package/dist/lib/neutral/chunk-LAF3LSWI.mjs.map +7 -0
  58. package/dist/lib/neutral/chunk-LMNRFOVB.mjs +108 -0
  59. package/dist/lib/neutral/chunk-LMNRFOVB.mjs.map +7 -0
  60. package/dist/lib/neutral/{chunk-WYOKA6AE.mjs → chunk-O6BH7EPN.mjs} +31 -4
  61. package/dist/lib/neutral/chunk-O6BH7EPN.mjs.map +7 -0
  62. package/dist/lib/neutral/{chunk-KTAWP7GI.mjs → chunk-OIYW7R2G.mjs} +99 -46
  63. package/dist/lib/neutral/chunk-OIYW7R2G.mjs.map +7 -0
  64. package/dist/lib/neutral/{chunk-TQQZLKB7.mjs → chunk-OYUG4FHF.mjs} +648 -1228
  65. package/dist/lib/neutral/chunk-OYUG4FHF.mjs.map +7 -0
  66. package/dist/lib/neutral/{chunk-NQRLRYJM.mjs → chunk-Q5FKCVBC.mjs} +173 -60
  67. package/dist/lib/neutral/chunk-Q5FKCVBC.mjs.map +7 -0
  68. package/dist/lib/neutral/chunk-Q62IHV2N.mjs +41 -0
  69. package/dist/lib/neutral/chunk-Q62IHV2N.mjs.map +7 -0
  70. package/dist/lib/neutral/{chunk-UFDK26FO.mjs → chunk-QVJDDG44.mjs} +69 -34
  71. package/dist/lib/neutral/chunk-QVJDDG44.mjs.map +7 -0
  72. package/dist/lib/neutral/{chunk-B5OXLWZL.mjs → chunk-TFEWTY5A.mjs} +155 -129
  73. package/dist/lib/neutral/chunk-TFEWTY5A.mjs.map +7 -0
  74. package/dist/lib/neutral/{chunk-UI6MWK5W.mjs → chunk-TTCSATUD.mjs} +1 -1
  75. package/dist/lib/neutral/{chunk-FZO7LQO7.mjs → chunk-VKWOFXT2.mjs} +22 -2
  76. package/dist/lib/neutral/{chunk-FZO7LQO7.mjs.map → chunk-VKWOFXT2.mjs.map} +1 -1
  77. package/dist/lib/neutral/{chunk-NXMFBIT5.mjs → chunk-ZACMEAYV.mjs} +89 -23
  78. package/dist/lib/neutral/chunk-ZACMEAYV.mjs.map +7 -0
  79. package/dist/lib/neutral/index.mjs +58 -38
  80. package/dist/lib/neutral/internal/index.mjs +131 -64
  81. package/dist/lib/neutral/meta.json +1 -1
  82. package/dist/lib/neutral/testing/index.mjs +222 -177
  83. package/dist/lib/neutral/testing/index.mjs.map +3 -3
  84. package/dist/types/src/Annotation.d.ts +108 -4
  85. package/dist/types/src/Annotation.d.ts.map +1 -1
  86. package/dist/types/src/Annotation.test.d.ts +2 -0
  87. package/dist/types/src/Annotation.test.d.ts.map +1 -0
  88. package/dist/types/src/Collection.d.ts +2 -3
  89. package/dist/types/src/Collection.d.ts.map +1 -1
  90. package/dist/types/src/Database.d.ts +56 -24
  91. package/dist/types/src/Database.d.ts.map +1 -1
  92. package/dist/types/src/Dataset.d.ts +17 -6
  93. package/dist/types/src/Dataset.d.ts.map +1 -1
  94. package/dist/types/src/Entity.d.ts +102 -26
  95. package/dist/types/src/Entity.d.ts.map +1 -1
  96. package/dist/types/src/Err.d.ts +27 -27
  97. package/dist/types/src/Err.d.ts.map +1 -1
  98. package/dist/types/src/Feed.d.ts +89 -25
  99. package/dist/types/src/Feed.d.ts.map +1 -1
  100. package/dist/types/src/Filter.d.ts +74 -11
  101. package/dist/types/src/Filter.d.ts.map +1 -1
  102. package/dist/types/src/Filter.test.d.ts +2 -0
  103. package/dist/types/src/Filter.test.d.ts.map +1 -0
  104. package/dist/types/src/Hypergraph.d.ts +14 -9
  105. package/dist/types/src/Hypergraph.d.ts.map +1 -1
  106. package/dist/types/src/Json.d.ts +33 -0
  107. package/dist/types/src/Json.d.ts.map +1 -0
  108. package/dist/types/src/Json.test.d.ts +2 -0
  109. package/dist/types/src/Json.test.d.ts.map +1 -0
  110. package/dist/types/src/JsonSchema.d.ts +2 -2
  111. package/dist/types/src/JsonSchema.d.ts.map +1 -1
  112. package/dist/types/src/Key.d.ts +1 -1
  113. package/dist/types/src/Key.d.ts.map +1 -1
  114. package/dist/types/src/Migration.d.ts +72 -0
  115. package/dist/types/src/Migration.d.ts.map +1 -0
  116. package/dist/types/src/Obj.d.ts +108 -65
  117. package/dist/types/src/Obj.d.ts.map +1 -1
  118. package/dist/types/src/Order.d.ts.map +1 -1
  119. package/dist/types/src/Query.d.ts +35 -10
  120. package/dist/types/src/Query.d.ts.map +1 -1
  121. package/dist/types/src/QueryResult.d.ts +9 -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 +72 -44
  128. package/dist/types/src/Relation.d.ts.map +1 -1
  129. package/dist/types/src/Scope.d.ts +34 -0
  130. package/dist/types/src/Scope.d.ts.map +1 -0
  131. package/dist/types/src/StateMap.d.ts +32 -0
  132. package/dist/types/src/StateMap.d.ts.map +1 -0
  133. package/dist/types/src/StateMap.test.d.ts +2 -0
  134. package/dist/types/src/StateMap.test.d.ts.map +1 -0
  135. package/dist/types/src/Tag.d.ts +21 -5
  136. package/dist/types/src/Tag.d.ts.map +1 -1
  137. package/dist/types/src/TagIndex.d.ts +36 -0
  138. package/dist/types/src/TagIndex.d.ts.map +1 -0
  139. package/dist/types/src/TagIndex.test.d.ts +2 -0
  140. package/dist/types/src/TagIndex.test.d.ts.map +1 -0
  141. package/dist/types/src/Tagging.d.ts +31 -0
  142. package/dist/types/src/Tagging.d.ts.map +1 -0
  143. package/dist/types/src/Type.d.ts +357 -96
  144. package/dist/types/src/Type.d.ts.map +1 -1
  145. package/dist/types/src/View.d.ts +2 -5
  146. package/dist/types/src/View.d.ts.map +1 -1
  147. package/dist/types/src/exemplars.test.d.ts +2 -0
  148. package/dist/types/src/exemplars.test.d.ts.map +1 -0
  149. package/dist/types/src/index.d.ts +8 -2
  150. package/dist/types/src/index.d.ts.map +1 -1
  151. package/dist/types/src/internal/Annotation/annotations.d.ts +79 -37
  152. package/dist/types/src/internal/Annotation/annotations.d.ts.map +1 -1
  153. package/dist/types/src/internal/Annotation/dictionary.d.ts +24 -0
  154. package/dist/types/src/internal/Annotation/dictionary.d.ts.map +1 -0
  155. package/dist/types/src/internal/Annotation/entity-dictionary.d.ts +14 -0
  156. package/dist/types/src/internal/Annotation/entity-dictionary.d.ts.map +1 -0
  157. package/dist/types/src/internal/Annotation/index.d.ts +4 -2
  158. package/dist/types/src/internal/Annotation/index.d.ts.map +1 -1
  159. package/dist/types/src/internal/Annotation/sorting.d.ts.map +1 -1
  160. package/dist/types/src/internal/Annotation/util.d.ts +14 -5
  161. package/dist/types/src/internal/Annotation/util.d.ts.map +1 -1
  162. package/dist/types/src/internal/Entity/api.d.ts +3 -3
  163. package/dist/types/src/internal/Entity/api.d.ts.map +1 -1
  164. package/dist/types/src/internal/Entity/entity.d.ts +72 -8
  165. package/dist/types/src/internal/Entity/entity.d.ts.map +1 -1
  166. package/dist/types/src/internal/Entity/guard.d.ts +10 -0
  167. package/dist/types/src/internal/Entity/guard.d.ts.map +1 -0
  168. package/dist/types/src/internal/Entity/index.d.ts +2 -0
  169. package/dist/types/src/internal/Entity/index.d.ts.map +1 -1
  170. package/dist/types/src/internal/Entity/model.d.ts +20 -17
  171. package/dist/types/src/internal/Entity/model.d.ts.map +1 -1
  172. package/dist/types/src/internal/Entity/object.d.ts +3 -3
  173. package/dist/types/src/internal/Entity/object.d.ts.map +1 -1
  174. package/dist/types/src/internal/Entity/relation.d.ts +30 -7
  175. package/dist/types/src/internal/Entity/relation.d.ts.map +1 -1
  176. package/dist/types/src/internal/Entity/type-kind.d.ts +24 -0
  177. package/dist/types/src/internal/Entity/type-kind.d.ts.map +1 -0
  178. package/dist/types/src/internal/Entity/type-uri.d.ts +25 -0
  179. package/dist/types/src/internal/Entity/type-uri.d.ts.map +1 -0
  180. package/dist/types/src/internal/Entity/version.d.ts.map +1 -1
  181. package/dist/types/src/internal/Format/date.d.ts.map +1 -1
  182. package/dist/types/src/internal/Format/format.d.ts +3 -2
  183. package/dist/types/src/internal/Format/format.d.ts.map +1 -1
  184. package/dist/types/src/internal/Format/index.d.ts +2 -2
  185. package/dist/types/src/internal/Format/index.d.ts.map +1 -1
  186. package/dist/types/src/internal/Format/number.d.ts.map +1 -1
  187. package/dist/types/src/internal/Format/object.d.ts +3 -1
  188. package/dist/types/src/internal/Format/object.d.ts.map +1 -1
  189. package/dist/types/src/internal/Format/types.d.ts.map +1 -1
  190. package/dist/types/src/internal/JsonSchema/json-schema-normalize.d.ts.map +1 -1
  191. package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts +28 -28
  192. package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts.map +1 -1
  193. package/dist/types/src/internal/JsonSchema/json-schema.d.ts +3 -2
  194. package/dist/types/src/internal/JsonSchema/json-schema.d.ts.map +1 -1
  195. package/dist/types/src/internal/Obj/clone.d.ts.map +1 -1
  196. package/dist/types/src/internal/Obj/common.d.ts.map +1 -1
  197. package/dist/types/src/internal/Obj/create-object.d.ts +11 -12
  198. package/dist/types/src/internal/Obj/create-object.d.ts.map +1 -1
  199. package/dist/types/src/internal/Obj/deleted.d.ts.map +1 -1
  200. package/dist/types/src/internal/Obj/index.d.ts +0 -1
  201. package/dist/types/src/internal/Obj/index.d.ts.map +1 -1
  202. package/dist/types/src/internal/Obj/json-serializer.d.ts +11 -10
  203. package/dist/types/src/internal/Obj/json-serializer.d.ts.map +1 -1
  204. package/dist/types/src/internal/Obj/set-value.d.ts +1 -1
  205. package/dist/types/src/internal/Obj/set-value.d.ts.map +1 -1
  206. package/dist/types/src/internal/Obj/snapshot.d.ts.map +1 -1
  207. package/dist/types/src/internal/Obj/typed-object.d.ts +1 -1
  208. package/dist/types/src/internal/Query.d.ts +10 -0
  209. package/dist/types/src/internal/Query.d.ts.map +1 -0
  210. package/dist/types/src/internal/Ref/ref-array.d.ts +2 -2
  211. package/dist/types/src/internal/Ref/ref-array.d.ts.map +1 -1
  212. package/dist/types/src/internal/Ref/ref.d.ts +42 -19
  213. package/dist/types/src/internal/Ref/ref.d.ts.map +1 -1
  214. package/dist/types/src/internal/Type/compose.d.ts.map +1 -1
  215. package/dist/types/src/internal/Type/index.d.ts +1 -2
  216. package/dist/types/src/internal/Type/index.d.ts.map +1 -1
  217. package/dist/types/src/internal/Type/manipulation.d.ts +0 -1
  218. package/dist/types/src/internal/Type/manipulation.d.ts.map +1 -1
  219. package/dist/types/src/internal/Type/type-schema.d.ts +52 -0
  220. package/dist/types/src/internal/Type/type-schema.d.ts.map +1 -0
  221. package/dist/types/src/internal/common/api/meta.d.ts +14 -11
  222. package/dist/types/src/internal/common/api/meta.d.ts.map +1 -1
  223. package/dist/types/src/internal/common/proxy/change-context.d.ts +1 -1
  224. package/dist/types/src/internal/common/proxy/change-context.d.ts.map +1 -1
  225. package/dist/types/src/internal/common/proxy/define-hidden-property.d.ts.map +1 -1
  226. package/dist/types/src/internal/common/proxy/errors.d.ts +1 -1
  227. package/dist/types/src/internal/common/proxy/errors.d.ts.map +1 -1
  228. package/dist/types/src/internal/common/proxy/event-batch.d.ts.map +1 -1
  229. package/dist/types/src/internal/common/proxy/json-serializer.d.ts.map +1 -1
  230. package/dist/types/src/internal/common/proxy/make-object.d.ts +11 -5
  231. package/dist/types/src/internal/common/proxy/make-object.d.ts.map +1 -1
  232. package/dist/types/src/internal/common/proxy/ownership.d.ts.map +1 -1
  233. package/dist/types/src/internal/common/proxy/proxy-utils.d.ts.map +1 -1
  234. package/dist/types/src/internal/common/proxy/reactive-array.d.ts +1 -1
  235. package/dist/types/src/internal/common/proxy/reactive.d.ts +1 -1
  236. package/dist/types/src/internal/common/proxy/reactive.d.ts.map +1 -1
  237. package/dist/types/src/internal/common/proxy/reactive.test.d.ts +2 -0
  238. package/dist/types/src/internal/common/proxy/reactive.test.d.ts.map +1 -0
  239. package/dist/types/src/internal/common/proxy/schema-validator.d.ts.map +1 -1
  240. package/dist/types/src/internal/common/proxy/typed-handler.d.ts +18 -2
  241. package/dist/types/src/internal/common/proxy/typed-handler.d.ts.map +1 -1
  242. package/dist/types/src/internal/common/types/base.d.ts +4 -4
  243. package/dist/types/src/internal/common/types/base.d.ts.map +1 -1
  244. package/dist/types/src/internal/common/types/entity.d.ts +63 -6
  245. package/dist/types/src/internal/common/types/entity.d.ts.map +1 -1
  246. package/dist/types/src/internal/common/types/index.d.ts +1 -1
  247. package/dist/types/src/internal/common/types/index.d.ts.map +1 -1
  248. package/dist/types/src/internal/common/types/meta.d.ts +23 -7
  249. package/dist/types/src/internal/common/types/meta.d.ts.map +1 -1
  250. package/dist/types/src/internal/common/types/model-symbols.d.ts +8 -4
  251. package/dist/types/src/internal/common/types/model-symbols.d.ts.map +1 -1
  252. package/dist/types/src/internal/common/types/typename.d.ts +7 -0
  253. package/dist/types/src/internal/common/types/typename.d.ts.map +1 -1
  254. package/dist/types/src/internal/common/types/version.d.ts +1 -1
  255. package/dist/types/src/internal/common/types/well-known-types.d.ts +11 -0
  256. package/dist/types/src/internal/common/types/well-known-types.d.ts.map +1 -0
  257. package/dist/types/src/internal/index.d.ts +2 -0
  258. package/dist/types/src/internal/index.d.ts.map +1 -1
  259. package/dist/types/src/testing/test-data.d.ts +8 -8
  260. package/dist/types/src/testing/test-data.d.ts.map +1 -1
  261. package/dist/types/src/testing/test-schema.d.ts +83 -89
  262. package/dist/types/src/testing/test-schema.d.ts.map +1 -1
  263. package/dist/types/src/testing/util.d.ts +5 -3
  264. package/dist/types/src/testing/util.d.ts.map +1 -1
  265. package/dist/types/tsconfig.tsbuildinfo +1 -1
  266. package/package.json +27 -19
  267. package/src/Annotation.test.ts +439 -0
  268. package/src/Annotation.ts +152 -4
  269. package/src/Collection.ts +6 -5
  270. package/src/Database.ts +117 -57
  271. package/src/Dataset.ts +10 -2
  272. package/src/Entity.test.ts +116 -6
  273. package/src/Entity.ts +130 -31
  274. package/src/Err.ts +4 -4
  275. package/src/Feed.ts +138 -43
  276. package/src/Filter.test.ts +90 -0
  277. package/src/Filter.ts +143 -27
  278. package/src/Hypergraph.ts +14 -9
  279. package/src/Json.test.ts +175 -0
  280. package/src/Json.ts +103 -0
  281. package/src/Key.ts +1 -1
  282. package/src/Migration.ts +114 -0
  283. package/src/Obj.test.ts +122 -19
  284. package/src/Obj.ts +279 -97
  285. package/src/Query.test.ts +317 -131
  286. package/src/Query.ts +181 -73
  287. package/src/QueryResult.ts +11 -0
  288. package/src/Ref.ts +22 -4
  289. package/src/Registry.ts +155 -0
  290. package/src/Relation.test.ts +10 -10
  291. package/src/Relation.ts +112 -71
  292. package/src/Scope.ts +50 -0
  293. package/src/StateMap.test.ts +56 -0
  294. package/src/StateMap.ts +99 -0
  295. package/src/Tag.md +88 -0
  296. package/src/Tag.ts +49 -6
  297. package/src/TagIndex.test.ts +57 -0
  298. package/src/TagIndex.ts +110 -0
  299. package/src/Tagging.ts +83 -0
  300. package/src/Type.test.ts +223 -18
  301. package/src/Type.ts +602 -132
  302. package/src/View.ts +11 -15
  303. package/src/exemplars.test.ts +21 -0
  304. package/src/index.ts +9 -3
  305. package/src/internal/Annotation/annotations.test.ts +82 -13
  306. package/src/internal/Annotation/annotations.ts +153 -115
  307. package/src/internal/Annotation/dictionary.ts +47 -0
  308. package/src/internal/Annotation/entity-dictionary.ts +40 -0
  309. package/src/internal/Annotation/index.ts +4 -2
  310. package/src/internal/Annotation/sorting.ts +0 -1
  311. package/src/internal/Annotation/util.ts +17 -8
  312. package/src/internal/Entity/api.ts +7 -8
  313. package/src/internal/Entity/entity.ts +196 -47
  314. package/src/internal/Entity/guard.ts +26 -0
  315. package/src/internal/Entity/index.ts +2 -0
  316. package/src/internal/Entity/model.ts +37 -28
  317. package/src/internal/Entity/object.ts +21 -6
  318. package/src/internal/Entity/relation.ts +68 -34
  319. package/src/internal/Entity/type-kind.ts +75 -0
  320. package/src/internal/Entity/type-uri.ts +87 -0
  321. package/src/internal/Entity/util.ts +10 -9
  322. package/src/internal/Entity/version.ts +0 -1
  323. package/src/internal/Format/date.test.ts +0 -1
  324. package/src/internal/Format/date.ts +0 -4
  325. package/src/internal/Format/format.test.ts +21 -1
  326. package/src/internal/Format/index.ts +2 -3
  327. package/src/internal/Format/object.ts +21 -4
  328. package/src/internal/Format/types.ts +1 -1
  329. package/src/internal/JsonSchema/annotations.ts +1 -1
  330. package/src/internal/JsonSchema/json-schema-type.ts +1 -1
  331. package/src/internal/JsonSchema/json-schema.test.ts +55 -142
  332. package/src/internal/JsonSchema/json-schema.ts +44 -31
  333. package/src/internal/Obj/clone.ts +9 -4
  334. package/src/internal/Obj/create-object.test.ts +13 -13
  335. package/src/internal/Obj/create-object.ts +68 -24
  336. package/src/internal/Obj/deleted.ts +1 -1
  337. package/src/internal/Obj/index.ts +0 -1
  338. package/src/internal/Obj/inspect.ts +4 -3
  339. package/src/internal/Obj/json-serializer.test.ts +102 -24
  340. package/src/internal/Obj/json-serializer.ts +105 -43
  341. package/src/internal/Obj/set-value.test.ts +31 -54
  342. package/src/internal/Obj/set-value.ts +1 -1
  343. package/src/internal/Obj/snapshot.ts +11 -4
  344. package/src/internal/Obj/typed-object.test.ts +9 -11
  345. package/src/internal/Obj/typed-object.ts +1 -1
  346. package/src/internal/Query.ts +159 -0
  347. package/src/internal/Ref/ref-array.ts +3 -4
  348. package/src/internal/Ref/ref.test.ts +17 -27
  349. package/src/internal/Ref/ref.ts +124 -59
  350. package/src/internal/Type/compose.test.ts +3 -2
  351. package/src/internal/Type/index.ts +1 -2
  352. package/src/internal/Type/manipulation.ts +0 -25
  353. package/src/internal/Type/type-schema.ts +60 -0
  354. package/src/internal/common/README.md +2 -2
  355. package/src/internal/common/api/meta.ts +19 -17
  356. package/src/internal/common/proxy/change-context.ts +1 -1
  357. package/src/internal/common/proxy/change.test.ts +118 -110
  358. package/src/internal/common/proxy/errors.ts +2 -2
  359. package/src/internal/common/proxy/handler.test.ts +1 -3
  360. package/src/internal/common/proxy/json-serializer.ts +26 -16
  361. package/src/internal/common/proxy/make-object.ts +43 -21
  362. package/src/internal/common/proxy/ownership.ts +2 -3
  363. package/src/internal/common/proxy/reactive-array.ts +1 -1
  364. package/src/internal/common/proxy/reactive.test.ts +54 -0
  365. package/src/internal/common/proxy/reactive.ts +11 -3
  366. package/src/internal/common/proxy/schema.test.ts +48 -86
  367. package/src/internal/common/proxy/typed-handler.test.ts +12 -12
  368. package/src/internal/common/proxy/typed-handler.ts +79 -19
  369. package/src/internal/common/proxy/typed-object.test.ts +16 -29
  370. package/src/internal/common/types/base.ts +4 -4
  371. package/src/internal/common/types/entity.ts +81 -2
  372. package/src/internal/common/types/index.ts +6 -1
  373. package/src/internal/common/types/meta.ts +49 -15
  374. package/src/internal/common/types/model-symbols.ts +16 -4
  375. package/src/internal/common/types/typename.ts +39 -3
  376. package/src/internal/common/types/well-known-types.ts +15 -0
  377. package/src/internal/index.ts +6 -0
  378. package/src/testing/api.test.ts +15 -10
  379. package/src/testing/test-data.ts +159 -100
  380. package/src/testing/test-schema.ts +22 -58
  381. package/src/testing/util.ts +14 -11
  382. package/dist/lib/neutral/SchemaRegistry.mjs +0 -2
  383. package/dist/lib/neutral/chunk-43Y5DOS6.mjs.map +0 -7
  384. package/dist/lib/neutral/chunk-724GQYEN.mjs +0 -56
  385. package/dist/lib/neutral/chunk-724GQYEN.mjs.map +0 -7
  386. package/dist/lib/neutral/chunk-ANHVGJI4.mjs.map +0 -7
  387. package/dist/lib/neutral/chunk-B5OXLWZL.mjs.map +0 -7
  388. package/dist/lib/neutral/chunk-BNCCGLJN.mjs +0 -7
  389. package/dist/lib/neutral/chunk-BNCCGLJN.mjs.map +0 -7
  390. package/dist/lib/neutral/chunk-BOZZPUXE.mjs.map +0 -7
  391. package/dist/lib/neutral/chunk-CIRHIEMW.mjs.map +0 -7
  392. package/dist/lib/neutral/chunk-DYDJBZEG.mjs +0 -102
  393. package/dist/lib/neutral/chunk-DYDJBZEG.mjs.map +0 -7
  394. package/dist/lib/neutral/chunk-FXEG7EOK.mjs.map +0 -7
  395. package/dist/lib/neutral/chunk-KTAWP7GI.mjs.map +0 -7
  396. package/dist/lib/neutral/chunk-NEGC54NE.mjs +0 -130
  397. package/dist/lib/neutral/chunk-NEGC54NE.mjs.map +0 -7
  398. package/dist/lib/neutral/chunk-NQRLRYJM.mjs.map +0 -7
  399. package/dist/lib/neutral/chunk-NXMFBIT5.mjs.map +0 -7
  400. package/dist/lib/neutral/chunk-OENWMTE6.mjs +0 -45
  401. package/dist/lib/neutral/chunk-OENWMTE6.mjs.map +0 -7
  402. package/dist/lib/neutral/chunk-OMUPQMLR.mjs.map +0 -7
  403. package/dist/lib/neutral/chunk-RMLF7JOZ.mjs +0 -97
  404. package/dist/lib/neutral/chunk-RMLF7JOZ.mjs.map +0 -7
  405. package/dist/lib/neutral/chunk-SEMVAGBM.mjs +0 -355
  406. package/dist/lib/neutral/chunk-SEMVAGBM.mjs.map +0 -7
  407. package/dist/lib/neutral/chunk-TQQZLKB7.mjs.map +0 -7
  408. package/dist/lib/neutral/chunk-UBEZSGXY.mjs.map +0 -7
  409. package/dist/lib/neutral/chunk-UFDK26FO.mjs.map +0 -7
  410. package/dist/lib/neutral/chunk-VA2F47ZC.mjs +0 -152
  411. package/dist/lib/neutral/chunk-VA2F47ZC.mjs.map +0 -7
  412. package/dist/lib/neutral/chunk-WYOKA6AE.mjs.map +0 -7
  413. package/dist/lib/neutral/chunk-YWXWXIE5.mjs.map +0 -7
  414. package/dist/types/src/SchemaRegistry.d.ts +0 -84
  415. package/dist/types/src/SchemaRegistry.d.ts.map +0 -1
  416. package/dist/types/src/internal/Obj/ids.d.ts +0 -6
  417. package/dist/types/src/internal/Obj/ids.d.ts.map +0 -1
  418. package/dist/types/src/internal/Type/echo-schema.d.ts +0 -181
  419. package/dist/types/src/internal/Type/echo-schema.d.ts.map +0 -1
  420. package/dist/types/src/internal/Type/persistent-schema.d.ts +0 -20
  421. package/dist/types/src/internal/Type/persistent-schema.d.ts.map +0 -1
  422. package/src/SchemaRegistry.ts +0 -106
  423. package/src/internal/Obj/ids.ts +0 -12
  424. package/src/internal/Type/echo-schema.ts +0 -424
  425. package/src/internal/Type/persistent-schema.ts +0 -33
  426. /package/dist/lib/neutral/{SchemaRegistry.mjs.map → Migration.mjs.map} +0 -0
  427. /package/dist/lib/neutral/{chunk-UTBRYVQC.mjs.map → chunk-G6CFWUYH.mjs.map} +0 -0
  428. /package/dist/lib/neutral/{chunk-UI6MWK5W.mjs.map → chunk-TTCSATUD.mjs.map} +0 -0
package/src/Annotation.ts CHANGED
@@ -7,10 +7,11 @@
7
7
  export {
8
8
  DescriptionAnnotation,
9
9
  FormInputAnnotation,
10
+ FormInlineAnnotation,
10
11
  GeneratorAnnotation,
11
12
  LabelAnnotation,
12
13
  ReferenceAnnotation,
13
- SystemTypeAnnotation,
14
+ HiddenAnnotation,
14
15
  TypeAnnotation,
15
16
  getDescriptionWithSchema,
16
17
  getLabelWithSchema,
@@ -18,12 +19,71 @@ export {
18
19
  setDescriptionWithSchema,
19
20
  setLabelWithSchema,
20
21
  IconAnnotation,
22
+ IconFromRefAnnotation,
21
23
  } from './internal/Annotation';
22
24
 
23
- import type * as Schema from 'effect/Schema';
25
+ import * as Function from 'effect/Function';
26
+ import * as Option from 'effect/Option';
27
+ import * as Schema from 'effect/Schema';
28
+ import * as SchemaAST from 'effect/SchemaAST';
29
+ import * as Types from 'effect/Types';
24
30
 
31
+ import * as Entity from './Entity';
25
32
  import * as internalAnnotations from './internal/Annotation';
26
33
 
34
+ export const TypeId = '~@dxos/echo/Annotation' as const;
35
+ export type TypeId = typeof TypeId;
36
+
37
+ // TODO(dmaretskyi): Reconcile different get/set styles: mutate in-place, return.
38
+ // TODO(dmaretskyi): Reconcile Annotation methods vs static functions.
39
+ // TODO(dmaretskyi): Reconcile Annotation.Key vs DXN -- work-out approach to versioning.
40
+
41
+ /**
42
+ * Annotation is a typed property that can be assigned to a schema or an entity instance.
43
+ */
44
+ export interface Annotation<T> {
45
+ [TypeId]: {
46
+ _Type: T;
47
+ };
48
+
49
+ // TODO(dmaretskyi): Make this a DXN?
50
+ /**
51
+ * Unique fully-qualified identifier for the annotation.
52
+ * @example "org.dxos.annotation.color"
53
+ */
54
+ readonly key: Key;
55
+
56
+ /**
57
+ * Schema of the annotation value.
58
+ */
59
+ readonly schema: Schema.Schema<T, unknown, never>;
60
+
61
+ /**
62
+ * Get the annotation value from an Effect schema.
63
+ *
64
+ * Only accepts `Schema.Schema.Any` — to read an annotation off a `Type.Type`
65
+ * entity, unwrap it first with `Type.getSchema(entity)`. This keeps the
66
+ * annotation pipeline single-shaped and forces annotations to live on the
67
+ * source schema, not on the post-construction Type entity.
68
+ */
69
+ get: (schema: Schema.Schema.Any) => Option.Option<T>;
70
+ /**
71
+ * Get the annotation value from the AST.
72
+ */
73
+ getFromAst: (ast: SchemaAST.AST) => Option.Option<T>;
74
+ /**
75
+ * Set the annotation on an Effect schema.
76
+ *
77
+ * Only accepts `Schema.Schema.Any` — annotations must be applied to the
78
+ * source schema BEFORE wrapping it with `Type.makeObject` / `Type.makeRelation`.
79
+ * In a pipe, place every `Annotation.X.set(...)` before the `Type.make...` step.
80
+ */
81
+ set: (value: T) => <S extends Schema.Schema.Any>(schema: S) => S;
82
+ }
83
+
84
+ export const Key = internalAnnotations.Key;
85
+ export type Key = Schema.Schema.Type<typeof Key>;
86
+
27
87
  interface MakeProps<T> {
28
88
  id: string;
29
89
  schema: Schema.Schema<T, any, never>;
@@ -44,5 +104,93 @@ interface MakeProps<T> {
44
104
  * const schema = Schema.String.annotations(ColorAnnotation.set('red'));
45
105
  * ```
46
106
  */
47
- export const make: <T>(props: MakeProps<T>) => internalAnnotations.AnnotationHelper<T> =
48
- internalAnnotations.makeUserAnnotation;
107
+ export const make: <T>(props: MakeProps<T>) => Annotation<T> = internalAnnotations.makeUserAnnotation;
108
+
109
+ /**
110
+ * Get the value of an annotation from an entity instance or snapshot.
111
+ * For schema-level reads use the annotation instance method (e.g. `ColorAnnotation.get(schema)`).
112
+ * For getting an annotation value from a dictionary, use `getDictionary`.
113
+ */
114
+ export const get: {
115
+ <T>(annotation: Annotation<T>): (target: Entity.Unknown | Entity.Snapshot) => Option.Option<T>;
116
+ <T>(target: Entity.Unknown | Entity.Snapshot, annotation: Annotation<T>): Option.Option<T>;
117
+ } = Function.dual<
118
+ <T>(annotation: Annotation<T>) => (target: Entity.Unknown | Entity.Snapshot) => Option.Option<T>,
119
+ <T>(target: Entity.Unknown | Entity.Snapshot, annotation: Annotation<T>) => Option.Option<T>
120
+ >(2, (target, annotation) => {
121
+ return internalAnnotations.get(target, annotation);
122
+ });
123
+
124
+ /**
125
+ * Set the value of an annotation on an entity instance.
126
+ * For schema-level writes use the annotation instance method (e.g. `ColorAnnotation.set('red')`).
127
+ * For setting an annotation value on a dictionary, use `setDictionary`.
128
+ */
129
+ export const set: {
130
+ <T>(annotation: Annotation<T>, value: T): (target: Entity.Mutable<Entity.Unknown>) => void;
131
+ <T>(target: Entity.Mutable<Entity.Unknown>, annotation: Annotation<T>, value: T): void;
132
+ } = Function.dual<
133
+ <T>(annotation: Annotation<T>, value: T) => (target: Entity.Mutable<Entity.Unknown>) => void,
134
+ <T>(target: Entity.Mutable<Entity.Unknown>, annotation: Annotation<T>, value: T) => void
135
+ >(3, (target, annotation, value) => {
136
+ return internalAnnotations.set(target, annotation, value);
137
+ });
138
+
139
+ export const getFromAst: {
140
+ <T>(annotation: Annotation<T>): (ast: SchemaAST.AST) => Option.Option<T>;
141
+ <T>(ast: SchemaAST.AST, annotation: Annotation<T>): Option.Option<T>;
142
+ } = Function.dual<
143
+ <T>(annotation: Annotation<T>) => (ast: SchemaAST.AST) => Option.Option<T>,
144
+ <T>(ast: SchemaAST.AST, annotation: Annotation<T>) => Option.Option<T>
145
+ >(2, (ast, annotation) => {
146
+ return internalAnnotations.getFromAst(ast, annotation);
147
+ });
148
+
149
+ /**
150
+ * Set of annotation values.
151
+ *
152
+ * Can be used inside an object/relation schema:
153
+ *
154
+ * ```ts
155
+ * const Person = Schema.Struct({
156
+ * name: Schema.String,
157
+ * extensions: Annotation.Dictionary,
158
+ * });
159
+ * ```
160
+ */
161
+ export const Dictionary = internalAnnotations.Dictionary;
162
+ export interface Dictionary extends Schema.Schema.Type<typeof Dictionary> {}
163
+
164
+ /**
165
+ * Get the value of an annotation from a Dictionary.
166
+ */
167
+ export const getDictionary: {
168
+ <T>(annotation: Annotation<T>): (values: Dictionary) => Option.Option<T>;
169
+ <T>(values: Dictionary, annotation: Annotation<T>): Option.Option<T>;
170
+ } = Function.dual<
171
+ <T>(annotation: Annotation<T>) => (values: Dictionary) => Option.Option<T>,
172
+ <T>(values: Dictionary, annotation: Annotation<T>) => Option.Option<T>
173
+ >(2, (values, annotation) => {
174
+ return internalAnnotations.getDictionary(values, annotation);
175
+ });
176
+
177
+ /**
178
+ * Set the value of an annotation in a Dictionary.
179
+ *
180
+ * Can also be used within Obj.update callback:
181
+ *
182
+ * ```ts
183
+ * Obj.update(obj, (obj) => {
184
+ * Annotation.setDictionary(obj.annotations, ColorAnnotation, 'red');
185
+ * });
186
+ * ```
187
+ */
188
+ export const setDictionary: {
189
+ <T>(annotation: Annotation<T>, value: T): (values: Dictionary) => void;
190
+ <T>(values: Types.Mutable<Dictionary>, annotation: Annotation<T>, value: T): void;
191
+ } = Function.dual<
192
+ <T>(annotation: Annotation<T>, value: T) => (values: Dictionary) => void,
193
+ <T>(values: Types.Mutable<Dictionary>, annotation: Annotation<T>, value: T) => void
194
+ >(3, (values, annotation, value) => {
195
+ return internalAnnotations.setDictionary(values, annotation, value);
196
+ });
package/src/Collection.ts CHANGED
@@ -6,6 +6,9 @@
6
6
 
7
7
  import * as Schema from 'effect/Schema';
8
8
 
9
+ import { DXN } from '@dxos/keys';
10
+
11
+ import * as Annotation from './Annotation';
9
12
  import * as internal from './internal';
10
13
  import * as Obj from './Obj';
11
14
  import * as Ref from './Ref';
@@ -18,13 +21,11 @@ export const Collection = Schema.Struct({
18
21
  name: Schema.String.pipe(Schema.optional),
19
22
  objects: Schema.Array(Ref.Ref(Obj.Unknown)).pipe(internal.FormInputAnnotation.set(false)),
20
23
  }).pipe(
21
- Type.object({
22
- typename: 'org.dxos.type.collection',
23
- version: '0.1.0',
24
- }),
24
+ Annotation.IconAnnotation.set({ icon: 'ph--folder--regular', hue: 'amber' }),
25
+ Type.makeObject(DXN.make('org.dxos.type.collection', '0.1.0')),
25
26
  );
26
27
 
27
- export interface Collection extends Schema.Schema.Type<typeof Collection> {}
28
+ export type Collection = Type.InstanceType<typeof Collection>;
28
29
 
29
30
  export const make = (props: Partial<Obj.MakeProps<typeof Collection>> = {}): Collection =>
30
31
  Obj.make(Collection, { objects: [], ...props });
package/src/Database.ts CHANGED
@@ -6,26 +6,28 @@
6
6
 
7
7
  import * as Context from 'effect/Context';
8
8
  import * as Effect from 'effect/Effect';
9
+ import * as Effectable from 'effect/Effectable';
9
10
  import * as Layer from 'effect/Layer';
10
11
  import * as Option from 'effect/Option';
11
12
  import * as Schema from 'effect/Schema';
12
- import type * as Types from 'effect/Types';
13
13
 
14
14
  import { promiseWithCauseCapture } from '@dxos/effect';
15
15
  import { invariant } from '@dxos/invariant';
16
- import { DXN, type SpaceId } from '@dxos/keys';
16
+ import { type SpaceId, type URI } from '@dxos/keys';
17
17
 
18
18
  import type * as Entity from './Entity';
19
19
  import * as Err from './Err';
20
20
  import type * as Filter from './Filter';
21
21
  import type * as Hypergraph from './Hypergraph';
22
- import { isInstanceOf } from './internal/Annotation';
22
+ import { type AnyProperties, EntityKind, KindId } from './internal/common/types';
23
+ // Deep import (not the `./internal/Entity` barrel) to avoid a cycle:
24
+ // Database → internal/Entity → entity → JsonSchema → Ref → Database.
25
+ import { isInstanceOf } from './internal/Entity/type-uri';
23
26
  import type { Ref } from './internal/Ref/ref';
24
- import { type AnyProperties } from './internal/common/types';
25
27
  import type * as Obj from './Obj';
26
28
  import type * as Query from './Query';
27
29
  import type * as QueryResult from './QueryResult';
28
- import type * as SchemaRegistry from './SchemaRegistry';
30
+ import type * as Registry from './Registry';
29
31
  import type * as Type from './Type';
30
32
 
31
33
  /**
@@ -38,7 +40,7 @@ export interface QueryFn {
38
40
  }
39
41
 
40
42
  /**
41
- * Common interface for Database and Queue.
43
+ * Common interface for Database, Feed, and Hypergraph.
42
44
  */
43
45
  export interface Queryable {
44
46
  query: QueryFn;
@@ -62,6 +64,16 @@ export type AddOptions = {
62
64
  placeIn?: ObjectPlacement;
63
65
  };
64
66
 
67
+ /**
68
+ * Rejects Type entities from {@link Database.add} at compile time via their `[KindId]` brand. Used
69
+ * as `T & RejectTypeEntity<T>` to preserve inference of `T`. Bounding `add` on
70
+ * `Obj.Unknown | Relation.Unknown` instead would reject broadly-typed instance adds (e.g.
71
+ * `Entity.Any`, `Obj.OfShape<T>`), forcing casts repo-wide.
72
+ */
73
+ export type RejectTypeEntity<T> = T extends { readonly [KindId]: EntityKind.Type }
74
+ ? { __error: 'Type entities must be persisted via db.addType(), not db.add().' }
75
+ : T;
76
+
65
77
  export type FlushOptions = {
66
78
  /**
67
79
  * Write any pending changes to disk.
@@ -96,11 +108,15 @@ export interface Database extends Queryable {
96
108
 
97
109
  get spaceId(): SpaceId;
98
110
 
99
- // TODO(burdon): Can we move this into graph?
100
- get schemaRegistry(): SchemaRegistry.SchemaRegistry;
101
-
102
111
  get graph(): Hypergraph.Hypergraph;
103
112
 
113
+ /**
114
+ * Registry for this database. Delegates type lookups to the shared hypergraph registry.
115
+ * To persist a schema so it replicates to other clients, add the type entity with
116
+ * {@link addType} (e.g. `await db.addType(Type.makeObjectFromJsonSchema(...))`).
117
+ */
118
+ readonly registry: Registry.Registry;
119
+
104
120
  toJSON(): object;
105
121
 
106
122
  /**
@@ -120,16 +136,28 @@ export interface Database extends Queryable {
120
136
  * Creates a reference to an existing object in the database.
121
137
  *
122
138
  * NOTE: The reference may be dangling if the object is not present in the database.
123
- * NOTE: Difference from `Ref.fromDXN`
124
- * `Ref.fromDXN(dxn)` returns an unhydrated reference. The `.load` and `.target` APIs will not work.
139
+ * NOTE: Difference from `Ref.fromURI`
140
+ * `Ref.fromURI(dxn)` returns an unhydrated reference. The `.load` and `.target` APIs will not work.
125
141
  * `db.makeRef(dxn)` is preferable in cases with access to the database.
126
142
  */
127
- makeRef<T extends Entity.Unknown = Entity.Unknown>(dxn: DXN): Ref<T>;
143
+ makeRef<T extends Entity.Unknown = Entity.Unknown>(uri: URI.URI): Ref<T>;
128
144
 
129
145
  /**
130
- * Adds object to the database.
146
+ * Adds an object or relation to the database.
147
+ *
148
+ * Only Object and Relation entities are accepted. To persist a Type definition use
149
+ * {@link addType} — passing a Type entity is rejected at compile time (and at runtime).
131
150
  */
132
- add<T extends Entity.Unknown = Entity.Unknown>(obj: T, opts?: AddOptions): T;
151
+ add<T extends Entity.Unknown = Entity.Unknown>(obj: T & RejectTypeEntity<T>, opts?: AddOptions): T;
152
+
153
+ /**
154
+ * Persists a Type definition (clones/forks the entity) so it replicates to other peers.
155
+ *
156
+ * Runs a conflict query first: if a type with the same typename + version already exists in
157
+ * this space, the existing persisted entity is returned and no duplicate is created. This is
158
+ * the only supported way to add Type entities — {@link add} rejects them.
159
+ */
160
+ addType<T extends Type.AnyEntity>(type: T): Promise<T>;
133
161
 
134
162
  /**
135
163
  * Removes object from the database.
@@ -201,19 +229,19 @@ export const spaceId = Effect.gen(function* () {
201
229
  */
202
230
  export const resolve: {
203
231
  // No type check.
204
- (ref: DXN | Ref<any>): Effect.Effect<Entity.Unknown, never, Service>;
232
+ (ref: URI.URI | Ref<any>): Effect.Effect<Entity.Unknown, never, Service>;
205
233
  // Check matches schema.
206
234
  <S extends Type.AnyEntity>(
207
- ref: DXN | Ref<any>,
235
+ ref: URI.URI | Ref<any>,
208
236
  schema: S,
209
- ): Effect.Effect<Schema.Schema.Type<S>, Err.ObjectNotFoundError, Service>;
237
+ ): Effect.Effect<Type.InstanceType<S>, Err.EntityNotFoundError, Service>;
210
238
  } = (<S extends Type.AnyEntity>(
211
- ref: DXN | Ref<any>,
239
+ ref: URI.URI | Ref<any>,
212
240
  schema?: S,
213
- ): Effect.Effect<Schema.Schema.Type<S>, Err.ObjectNotFoundError, Service> =>
241
+ ): Effect.Effect<Type.InstanceType<S>, Err.EntityNotFoundError, Service> =>
214
242
  Effect.gen(function* () {
215
243
  const { db } = yield* Service;
216
- const dxn = ref instanceof DXN ? ref : ref.dxn;
244
+ const dxn = typeof ref === 'string' ? ref : ref.uri;
217
245
  const object = yield* promiseWithCauseCapture(() =>
218
246
  db.graph
219
247
  .createRefResolver({
@@ -225,93 +253,125 @@ export const resolve: {
225
253
  );
226
254
 
227
255
  if (!object) {
228
- return yield* Effect.fail(new Err.ObjectNotFoundError(dxn));
256
+ return yield* Effect.fail(new Err.EntityNotFoundError(dxn));
229
257
  }
230
- invariant(!schema || isInstanceOf(schema, object), 'Object type mismatch.');
258
+ // `isInstanceOf` uses a conditional generic that TS can't resolve through
259
+ // the local `S extends Type.AnyEntity` parameter — runtime accepts it fine.
260
+ invariant(!schema || isInstanceOf(schema as any, object), 'Object type mismatch.');
231
261
  return object as any;
232
- })) as any;
262
+ }).pipe(Effect.withSpan('Database.resolve'))) as any;
233
263
 
234
264
  /**
235
265
  * Loads an object reference.
236
266
  */
237
- export const load: <T>(ref: Ref<T>) => Effect.Effect<T, Err.ObjectNotFoundError, never> = Effect.fn(function* (ref) {
238
- const object = yield* promiseWithCauseCapture(() => ref.tryLoad());
239
- if (!object) {
240
- return yield* Effect.fail(new Err.ObjectNotFoundError(ref.dxn));
241
- }
242
- return object;
243
- });
267
+ export const load: <T>(ref: Ref<T>) => Effect.Effect<T, Err.EntityNotFoundError, never> = Effect.fn('Database.load')(
268
+ function* (ref) {
269
+ const object = yield* promiseWithCauseCapture(() => ref.tryLoad());
270
+ if (!object) {
271
+ return yield* Effect.fail(new Err.EntityNotFoundError(ref.uri));
272
+ }
273
+ return object;
274
+ },
275
+ );
244
276
 
245
277
  /**
246
278
  * Loads an object reference option.
247
279
  */
248
280
  // TODO(dmaretskyi): Do we need this -- you can just use `Effect.catchTag` in calling code instead.
249
- export const loadOption: <T>(ref: Ref<T>) => Effect.Effect<Option.Option<T>, never, never> = Effect.fn(function* (ref) {
250
- const object = yield* load(ref).pipe(Effect.catchTag('ObjectNotFoundError', () => Effect.succeed(undefined)));
281
+ export const loadOption: <T>(ref: Ref<T>) => Effect.Effect<Option.Option<T>, never, never> = Effect.fn(
282
+ 'Database.loadOption',
283
+ )(function* (ref) {
284
+ const object = yield* load(ref).pipe(Effect.catchTag('EntityNotFoundError', () => Effect.succeed(undefined)));
251
285
 
252
286
  return Option.fromNullable(object);
253
287
  });
254
288
 
255
289
  /**
256
- * Adds an object to the database.
290
+ * Adds an object or relation to the database.
257
291
  * @see {@link Database.add}
258
292
  */
259
- export const add = <T extends Entity.Unknown>(obj: T): Effect.Effect<T, never, Service> =>
260
- Service.pipe(Effect.map(({ db }) => db.add(obj)));
293
+ export const add = <T extends Entity.Unknown>(obj: T & RejectTypeEntity<T>): Effect.Effect<T, never, Service> =>
294
+ Service.pipe(Effect.map(({ db }) => db.add<T>(obj))).pipe(Effect.withSpan('Database.add'));
295
+
296
+ /**
297
+ * Persists a Type definition to the database.
298
+ * @see {@link Database.addType}
299
+ */
300
+ export const addType = <T extends Type.AnyEntity>(type: T): Effect.Effect<T, never, Service> =>
301
+ Service.pipe(Effect.flatMap(({ db }) => promiseWithCauseCapture(() => db.addType(type)))).pipe(
302
+ Effect.withSpan('Database.addType'),
303
+ );
261
304
 
262
305
  /**
263
306
  * Removes an object from the database.
264
307
  * @see {@link Database.remove}
265
308
  */
266
309
  export const remove = <T extends Entity.Unknown>(obj: T): Effect.Effect<void, never, Service> =>
267
- Service.pipe(Effect.map(({ db }) => db.remove(obj)));
310
+ Service.pipe(Effect.map(({ db }) => db.remove(obj))).pipe(Effect.withSpan('Database.remove'));
268
311
 
269
312
  /**
270
313
  * Flushes pending changes to disk.
271
314
  * @see {@link Database.flush}
272
315
  */
273
316
  export const flush = (opts?: FlushOptions) =>
274
- Service.pipe(Effect.flatMap(({ db }) => promiseWithCauseCapture(() => db.flush(opts))));
317
+ Service.pipe(Effect.flatMap(({ db }) => promiseWithCauseCapture(() => db.flush(opts)))).pipe(
318
+ Effect.withSpan('Database.flush'),
319
+ );
275
320
 
276
321
  /**
277
322
  * Creates a `QueryResult` object that can be subscribed to.
278
323
  */
279
324
  export const query: {
280
- <Q extends Query.Any>(query: Q): Effect.Effect<QueryResult.QueryResult<Query.Type<Q>>, never, Service>;
281
- <F extends Filter.Any>(filter: F): Effect.Effect<QueryResult.QueryResult<Filter.Type<F>>, never, Service>;
325
+ <Q extends Query.Any>(query: Q): QueryResult.QueryResultEffect<Query.Type<Q>, never, Service>;
326
+ <F extends Filter.Any>(filter: F): QueryResult.QueryResultEffect<Filter.Type<F>, never, Service>;
282
327
  } = (queryOrFilter: Query.Any | Filter.Any) =>
283
328
  Service.pipe(
284
329
  Effect.map(({ db }) => db.query(queryOrFilter as any) as QueryResult.QueryResult<any>),
285
330
  Effect.withSpan('Database.query'),
331
+ makeQueryResultEffect,
286
332
  );
287
333
 
288
334
  /**
289
335
  * Executes the query once and returns the results.
336
+ * @deprecated Use `yield* query(...).run` instead.
290
337
  */
291
338
  export const runQuery: {
292
339
  <Q extends Query.Any>(query: Q): Effect.Effect<Query.Type<Q>[], never, Service>;
293
340
  <F extends Filter.Any>(filter: F): Effect.Effect<Filter.Type<F>[], never, Service>;
294
341
  } = (queryOrFilter: Query.Any | Filter.Any) =>
295
- query(queryOrFilter as any).pipe(Effect.flatMap((queryResult) => promiseWithCauseCapture(() => queryResult.run())));
296
-
297
- /**
298
- * Creates a schema query result that can be subscribed to.
299
- */
300
- // TODO(dmaretskyi): Change API to `yield* Database.querySchema(...).first` and `yield* Database.querySchema(...).schema`.
301
- export const schemaQuery = <Q extends Types.NoExcessProperties<SchemaRegistry.Query, Q>>(
302
- schemaQueryOptions?: Q & SchemaRegistry.Query,
303
- ): Effect.Effect<QueryResult.QueryResult<SchemaRegistry.ExtractQueryResult<Q>>, never, Service> =>
304
- Service.pipe(
305
- Effect.map(({ db }) => db.schemaRegistry.query(schemaQueryOptions)),
306
- Effect.withSpan('Database.schemaQuery'),
342
+ query(queryOrFilter as any).pipe(
343
+ Effect.flatMap((queryResult) => promiseWithCauseCapture(() => queryResult.run())),
344
+ Effect.withSpan('Database.runQuery'),
307
345
  );
308
346
 
309
347
  /**
310
- * Executes a schema query once and returns the results.
348
+ * Executes the query once and returns the first result as or None.
349
+ * @deprecated Use `yield* query(...).first` instead.
311
350
  */
312
- export const runSchemaQuery = <Q extends Types.NoExcessProperties<SchemaRegistry.Query, Q>>(
313
- schemaQueryOptions?: Q & SchemaRegistry.Query,
314
- ): Effect.Effect<SchemaRegistry.ExtractQueryResult<Q>[], never, Service> =>
315
- schemaQuery(schemaQueryOptions).pipe(
316
- Effect.flatMap((queryResult) => promiseWithCauseCapture(() => queryResult.run())),
351
+ export const runQueryFirst: {
352
+ <Q extends Query.Any>(query: Q): Effect.Effect<Option.Option<Query.Type<Q>>, never, Service>;
353
+ <F extends Filter.Any>(filter: F): Effect.Effect<Option.Option<Filter.Type<F>>, never, Service>;
354
+ } = (queryOrFilter: Query.Any | Filter.Any) =>
355
+ query(queryOrFilter as any).pipe(
356
+ Effect.flatMap((queryResult) =>
357
+ promiseWithCauseCapture(async () => Option.fromNullable(await queryResult.firstOrUndefined())),
358
+ ),
359
+ Effect.withSpan('Database.runQueryFirst'),
317
360
  );
361
+
362
+ const makeQueryResultEffect = <T>(
363
+ eff: Effect.Effect<QueryResult.QueryResult<T>, never, Service>,
364
+ ): QueryResult.QueryResultEffect<T, never, Service> => {
365
+ return {
366
+ run: Effect.flatMap(eff, (result) => promiseWithCauseCapture(() => result.run())),
367
+ first: Effect.flatMap(eff, (result) =>
368
+ promiseWithCauseCapture(async () => Option.fromNullable(await result.firstOrUndefined())),
369
+ ),
370
+
371
+ // Effect internals
372
+ ...Effectable.CommitPrototype,
373
+ commit() {
374
+ return eff;
375
+ },
376
+ } as any;
377
+ };
package/src/Dataset.ts CHANGED
@@ -11,13 +11,21 @@ import * as Schema from 'effect/Schema';
11
11
  import * as Collection from './Collection';
12
12
  import * as Feed from './Feed';
13
13
  import * as Obj from './Obj';
14
+ import * as Type from './Type';
14
15
  import * as View from './View';
15
16
 
16
17
  /**
17
- * Abstart set of objects, represented by a view, feed, or collection.
18
+ * Abstract set of objects, represented by a view, feed, or collection.
19
+ * Schema-level union of the underlying type entities (rebuilt via
20
+ * `Type.getSchema`) so this can still be consumed by Schema-side APIs such
21
+ * as `Filter.type(...)` on a union.
18
22
  */
19
- export const Dataset = Schema.Union(Feed.Feed, Collection.Collection, View.View);
20
23
  export type Dataset = Feed.Feed | Collection.Collection | View.View;
24
+ export const Dataset = Schema.Union(
25
+ Type.getSchema(Feed.Feed),
26
+ Type.getSchema(Collection.Collection),
27
+ Type.getSchema(View.View),
28
+ );
21
29
 
22
30
  export const isDataset: (value: unknown) => value is Dataset = pipe(
23
31
  Obj.instanceOf(Feed.Feed),
@@ -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
  });