@dxos/echo 0.8.4-main.b97322e → 0.8.4-main.c4373fc

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 (315) hide show
  1. package/README.md +1 -1
  2. package/dist/lib/browser/chunk-MWLA34S5.mjs +3843 -0
  3. package/dist/lib/browser/chunk-MWLA34S5.mjs.map +7 -0
  4. package/dist/lib/browser/chunk-OAZJQHVO.mjs +453 -0
  5. package/dist/lib/browser/chunk-OAZJQHVO.mjs.map +7 -0
  6. package/dist/lib/browser/chunk-ORIE2FMS.mjs +514 -0
  7. package/dist/lib/browser/chunk-ORIE2FMS.mjs.map +7 -0
  8. package/dist/lib/browser/index.mjs +26 -5
  9. package/dist/lib/browser/internal/index.mjs +326 -0
  10. package/dist/lib/browser/internal/index.mjs.map +7 -0
  11. package/dist/lib/browser/meta.json +1 -1
  12. package/dist/lib/browser/query/index.mjs +23 -0
  13. package/dist/lib/browser/query/index.mjs.map +7 -0
  14. package/dist/lib/browser/testing/index.mjs +260 -32
  15. package/dist/lib/browser/testing/index.mjs.map +4 -4
  16. package/dist/lib/node-esm/chunk-AXWVDOP7.mjs +453 -0
  17. package/dist/lib/node-esm/chunk-AXWVDOP7.mjs.map +7 -0
  18. package/dist/lib/node-esm/chunk-L4PBAJDP.mjs +514 -0
  19. package/dist/lib/node-esm/chunk-L4PBAJDP.mjs.map +7 -0
  20. package/dist/lib/node-esm/chunk-YTNLFBIK.mjs +3843 -0
  21. package/dist/lib/node-esm/chunk-YTNLFBIK.mjs.map +7 -0
  22. package/dist/lib/node-esm/index.mjs +26 -5
  23. package/dist/lib/node-esm/internal/index.mjs +326 -0
  24. package/dist/lib/node-esm/internal/index.mjs.map +7 -0
  25. package/dist/lib/node-esm/meta.json +1 -1
  26. package/dist/lib/node-esm/query/index.mjs +23 -0
  27. package/dist/lib/node-esm/query/index.mjs.map +7 -0
  28. package/dist/lib/node-esm/testing/index.mjs +260 -32
  29. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  30. package/dist/types/src/Obj.d.ts +111 -17
  31. package/dist/types/src/Obj.d.ts.map +1 -1
  32. package/dist/types/src/Ref.d.ts +1 -1
  33. package/dist/types/src/Ref.d.ts.map +1 -1
  34. package/dist/types/src/Relation.d.ts +11 -8
  35. package/dist/types/src/Relation.d.ts.map +1 -1
  36. package/dist/types/src/Type.d.ts +17 -18
  37. package/dist/types/src/Type.d.ts.map +1 -1
  38. package/dist/types/src/errors.d.ts +72 -0
  39. package/dist/types/src/errors.d.ts.map +1 -0
  40. package/dist/types/src/index.d.ts +3 -1
  41. package/dist/types/src/index.d.ts.map +1 -1
  42. package/dist/types/src/internal/ast/annotation-helper.d.ts +8 -0
  43. package/dist/types/src/internal/ast/annotation-helper.d.ts.map +1 -0
  44. package/dist/types/src/internal/ast/annotations.d.ts +119 -0
  45. package/dist/types/src/internal/ast/annotations.d.ts.map +1 -0
  46. package/dist/types/src/internal/ast/annotations.test.d.ts +2 -0
  47. package/dist/types/src/internal/ast/annotations.test.d.ts.map +1 -0
  48. package/dist/types/src/internal/ast/entity-kind.d.ts +10 -0
  49. package/dist/types/src/internal/ast/entity-kind.d.ts.map +1 -0
  50. package/dist/types/src/internal/ast/index.d.ts +5 -0
  51. package/dist/types/src/internal/ast/index.d.ts.map +1 -0
  52. package/dist/types/src/internal/ast/types.d.ts +6 -0
  53. package/dist/types/src/internal/ast/types.d.ts.map +1 -0
  54. package/dist/types/src/internal/formats/date.d.ts +63 -0
  55. package/dist/types/src/internal/formats/date.d.ts.map +1 -0
  56. package/dist/types/src/internal/formats/date.test.d.ts +2 -0
  57. package/dist/types/src/internal/formats/date.test.d.ts.map +1 -0
  58. package/dist/types/src/internal/formats/format.d.ts +30 -0
  59. package/dist/types/src/internal/formats/format.d.ts.map +1 -0
  60. package/dist/types/src/internal/formats/format.test.d.ts +2 -0
  61. package/dist/types/src/internal/formats/format.test.d.ts.map +1 -0
  62. package/dist/types/src/internal/formats/index.d.ts +8 -0
  63. package/dist/types/src/internal/formats/index.d.ts.map +1 -0
  64. package/dist/types/src/internal/formats/number.d.ts +31 -0
  65. package/dist/types/src/internal/formats/number.d.ts.map +1 -0
  66. package/dist/types/src/internal/formats/object.d.ts +35 -0
  67. package/dist/types/src/internal/formats/object.d.ts.map +1 -0
  68. package/dist/types/src/internal/formats/select.d.ts +11 -0
  69. package/dist/types/src/internal/formats/select.d.ts.map +1 -0
  70. package/dist/types/src/internal/formats/string.d.ts +38 -0
  71. package/dist/types/src/internal/formats/string.d.ts.map +1 -0
  72. package/dist/types/src/internal/formats/types.d.ts +68 -0
  73. package/dist/types/src/internal/formats/types.d.ts.map +1 -0
  74. package/dist/types/src/internal/index.d.ts +15 -0
  75. package/dist/types/src/internal/index.d.ts.map +1 -0
  76. package/dist/types/src/internal/json/annotations.d.ts +19 -0
  77. package/dist/types/src/internal/json/annotations.d.ts.map +1 -0
  78. package/dist/types/src/internal/json/effect-schema.test.d.ts +2 -0
  79. package/dist/types/src/internal/json/effect-schema.test.d.ts.map +1 -0
  80. package/dist/types/src/internal/json/index.d.ts +2 -0
  81. package/dist/types/src/internal/json/index.d.ts.map +1 -0
  82. package/dist/types/src/internal/json/json-schema.d.ts +32 -0
  83. package/dist/types/src/internal/json/json-schema.d.ts.map +1 -0
  84. package/dist/types/src/internal/json/json-schema.test.d.ts +2 -0
  85. package/dist/types/src/internal/json/json-schema.test.d.ts.map +1 -0
  86. package/dist/types/src/internal/json-schema/index.d.ts +3 -0
  87. package/dist/types/src/internal/json-schema/index.d.ts.map +1 -0
  88. package/dist/types/src/internal/json-schema/json-schema-normalize.d.ts +7 -0
  89. package/dist/types/src/internal/json-schema/json-schema-normalize.d.ts.map +1 -0
  90. package/dist/types/src/internal/json-schema/json-schema-type.d.ts +250 -0
  91. package/dist/types/src/internal/json-schema/json-schema-type.d.ts.map +1 -0
  92. package/dist/types/src/internal/object/accessors.d.ts +29 -0
  93. package/dist/types/src/internal/object/accessors.d.ts.map +1 -0
  94. package/dist/types/src/internal/object/common.d.ts +18 -0
  95. package/dist/types/src/internal/object/common.d.ts.map +1 -0
  96. package/dist/types/src/internal/object/create.d.ts +40 -0
  97. package/dist/types/src/internal/object/create.d.ts.map +1 -0
  98. package/dist/types/src/internal/object/create.test.d.ts +2 -0
  99. package/dist/types/src/internal/object/create.test.d.ts.map +1 -0
  100. package/dist/types/src/internal/object/deleted.d.ts +6 -0
  101. package/dist/types/src/internal/object/deleted.d.ts.map +1 -0
  102. package/dist/types/src/internal/object/entity.d.ts +22 -0
  103. package/dist/types/src/internal/object/entity.d.ts.map +1 -0
  104. package/dist/types/src/internal/object/expando.d.ts +14 -0
  105. package/dist/types/src/internal/object/expando.d.ts.map +1 -0
  106. package/dist/types/src/internal/object/ids.d.ts +6 -0
  107. package/dist/types/src/internal/object/ids.d.ts.map +1 -0
  108. package/dist/types/src/internal/object/index.d.ts +17 -0
  109. package/dist/types/src/internal/object/index.d.ts.map +1 -0
  110. package/dist/types/src/internal/object/inspect.d.ts +2 -0
  111. package/dist/types/src/internal/object/inspect.d.ts.map +1 -0
  112. package/dist/types/src/internal/object/json-serializer.d.ts +32 -0
  113. package/dist/types/src/internal/object/json-serializer.d.ts.map +1 -0
  114. package/dist/types/src/internal/object/json-serializer.test.d.ts +2 -0
  115. package/dist/types/src/internal/object/json-serializer.test.d.ts.map +1 -0
  116. package/dist/types/src/internal/object/meta.d.ts +31 -0
  117. package/dist/types/src/internal/object/meta.d.ts.map +1 -0
  118. package/dist/types/src/internal/object/model.d.ts +117 -0
  119. package/dist/types/src/internal/object/model.d.ts.map +1 -0
  120. package/dist/types/src/internal/object/relation.d.ts +17 -0
  121. package/dist/types/src/internal/object/relation.d.ts.map +1 -0
  122. package/dist/types/src/internal/object/schema-validator.d.ts +15 -0
  123. package/dist/types/src/internal/object/schema-validator.d.ts.map +1 -0
  124. package/dist/types/src/internal/object/schema-validator.test.d.ts +2 -0
  125. package/dist/types/src/internal/object/schema-validator.test.d.ts.map +1 -0
  126. package/dist/types/src/internal/object/typed-object.d.ts +31 -0
  127. package/dist/types/src/internal/object/typed-object.d.ts.map +1 -0
  128. package/dist/types/src/internal/object/typed-object.test.d.ts +2 -0
  129. package/dist/types/src/internal/object/typed-object.test.d.ts.map +1 -0
  130. package/dist/types/src/internal/object/typed-relation.d.ts +32 -0
  131. package/dist/types/src/internal/object/typed-relation.d.ts.map +1 -0
  132. package/dist/types/src/internal/object/typename.d.ts +15 -0
  133. package/dist/types/src/internal/object/typename.d.ts.map +1 -0
  134. package/dist/types/src/internal/object/version.d.ts +14 -0
  135. package/dist/types/src/internal/object/version.d.ts.map +1 -0
  136. package/dist/types/src/internal/projection/compose.d.ts +6 -0
  137. package/dist/types/src/internal/projection/compose.d.ts.map +1 -0
  138. package/dist/types/src/internal/projection/compose.test.d.ts +2 -0
  139. package/dist/types/src/internal/projection/compose.test.d.ts.map +1 -0
  140. package/dist/types/src/internal/projection/index.d.ts +2 -0
  141. package/dist/types/src/internal/projection/index.d.ts.map +1 -0
  142. package/dist/types/src/internal/proxy/handler.test.d.ts +2 -0
  143. package/dist/types/src/internal/proxy/handler.test.d.ts.map +1 -0
  144. package/dist/types/src/internal/proxy/reactive-object.d.ts +15 -0
  145. package/dist/types/src/internal/proxy/reactive-object.d.ts.map +1 -0
  146. package/dist/types/src/internal/proxy/schema.test.d.ts +2 -0
  147. package/dist/types/src/internal/proxy/schema.test.d.ts.map +1 -0
  148. package/dist/types/src/internal/proxy/typed-handler.d.ts +44 -0
  149. package/dist/types/src/internal/proxy/typed-handler.d.ts.map +1 -0
  150. package/dist/types/src/internal/proxy/typed-handler.test.d.ts +2 -0
  151. package/dist/types/src/internal/proxy/typed-handler.test.d.ts.map +1 -0
  152. package/dist/types/src/internal/proxy/typed-object.test.d.ts +2 -0
  153. package/dist/types/src/internal/proxy/typed-object.test.d.ts.map +1 -0
  154. package/dist/types/src/internal/query/index.d.ts +2 -0
  155. package/dist/types/src/internal/query/index.d.ts.map +1 -0
  156. package/dist/types/src/internal/query/query.d.ts +17 -0
  157. package/dist/types/src/internal/query/query.d.ts.map +1 -0
  158. package/dist/types/src/internal/ref/index.d.ts +3 -0
  159. package/dist/types/src/internal/ref/index.d.ts.map +1 -0
  160. package/dist/types/src/internal/ref/ref-array.d.ts +21 -0
  161. package/dist/types/src/internal/ref/ref-array.d.ts.map +1 -0
  162. package/dist/types/src/internal/ref/ref.d.ts +206 -0
  163. package/dist/types/src/internal/ref/ref.d.ts.map +1 -0
  164. package/dist/types/src/internal/ref/ref.test.d.ts +2 -0
  165. package/dist/types/src/internal/ref/ref.test.d.ts.map +1 -0
  166. package/dist/types/src/internal/schema/echo-schema.d.ts +168 -0
  167. package/dist/types/src/internal/schema/echo-schema.d.ts.map +1 -0
  168. package/dist/types/src/internal/schema/index.d.ts +7 -0
  169. package/dist/types/src/internal/schema/index.d.ts.map +1 -0
  170. package/dist/types/src/internal/schema/manipulation.d.ts +10 -0
  171. package/dist/types/src/internal/schema/manipulation.d.ts.map +1 -0
  172. package/dist/types/src/internal/schema/runtime-schema-registry.d.ts +18 -0
  173. package/dist/types/src/internal/schema/runtime-schema-registry.d.ts.map +1 -0
  174. package/dist/types/src/internal/schema/snapshot.d.ts +6 -0
  175. package/dist/types/src/internal/schema/snapshot.d.ts.map +1 -0
  176. package/dist/types/src/internal/schema/stored-schema.d.ts +13 -0
  177. package/dist/types/src/internal/schema/stored-schema.d.ts.map +1 -0
  178. package/dist/types/src/internal/testing/index.d.ts +3 -0
  179. package/dist/types/src/internal/testing/index.d.ts.map +1 -0
  180. package/dist/types/src/internal/testing/types.d.ts +455 -0
  181. package/dist/types/src/internal/testing/types.d.ts.map +1 -0
  182. package/dist/types/src/internal/testing/utils.d.ts +10 -0
  183. package/dist/types/src/internal/testing/utils.d.ts.map +1 -0
  184. package/dist/types/src/internal/types/index.d.ts +3 -0
  185. package/dist/types/src/internal/types/index.d.ts.map +1 -0
  186. package/dist/types/src/internal/types/types.d.ts +79 -0
  187. package/dist/types/src/internal/types/types.d.ts.map +1 -0
  188. package/dist/types/src/internal/types/types.test.d.ts +2 -0
  189. package/dist/types/src/internal/types/types.test.d.ts.map +1 -0
  190. package/dist/types/src/internal/types/util.d.ts +5 -0
  191. package/dist/types/src/internal/types/util.d.ts.map +1 -0
  192. package/dist/types/src/query/index.d.ts +2 -1
  193. package/dist/types/src/query/index.d.ts.map +1 -1
  194. package/dist/types/src/query/{dsl.d.ts → query.d.ts} +44 -15
  195. package/dist/types/src/query/query.d.ts.map +1 -0
  196. package/dist/types/src/query/query.test.d.ts +2 -0
  197. package/dist/types/src/query/query.test.d.ts.map +1 -0
  198. package/dist/types/src/query/tag.d.ts +18 -0
  199. package/dist/types/src/query/tag.d.ts.map +1 -0
  200. package/dist/types/src/testing/echo-schema.d.ts +7 -0
  201. package/dist/types/src/testing/echo-schema.d.ts.map +1 -0
  202. package/dist/types/src/testing/index.d.ts +2 -0
  203. package/dist/types/src/testing/index.d.ts.map +1 -1
  204. package/dist/types/src/testing/types.d.ts +18 -18
  205. package/dist/types/src/testing/types.d.ts.map +1 -1
  206. package/dist/types/tsconfig.tsbuildinfo +1 -1
  207. package/package.json +34 -16
  208. package/src/Obj.ts +250 -27
  209. package/src/Ref.ts +1 -2
  210. package/src/Relation.ts +25 -13
  211. package/src/Type.ts +32 -31
  212. package/src/errors.ts +18 -0
  213. package/src/index.ts +4 -1
  214. package/src/internal/ast/annotation-helper.ts +22 -0
  215. package/src/internal/ast/annotations.test.ts +98 -0
  216. package/src/internal/ast/annotations.ts +212 -0
  217. package/src/internal/ast/entity-kind.ts +15 -0
  218. package/src/internal/ast/index.ts +8 -0
  219. package/src/internal/ast/types.ts +17 -0
  220. package/src/internal/formats/date.test.ts +56 -0
  221. package/src/internal/formats/date.ts +217 -0
  222. package/src/internal/formats/format.test.ts +77 -0
  223. package/src/internal/formats/format.ts +52 -0
  224. package/src/internal/formats/index.ts +12 -0
  225. package/src/internal/formats/number.ts +89 -0
  226. package/src/internal/formats/object.ts +80 -0
  227. package/src/internal/formats/select.ts +16 -0
  228. package/src/internal/formats/string.ts +76 -0
  229. package/src/internal/formats/types.ts +175 -0
  230. package/src/internal/index.ts +22 -0
  231. package/src/internal/json/annotations.ts +50 -0
  232. package/src/internal/json/effect-schema.test.ts +143 -0
  233. package/src/internal/json/index.ts +5 -0
  234. package/src/internal/json/json-schema.test.ts +726 -0
  235. package/src/internal/json/json-schema.ts +548 -0
  236. package/src/internal/json-schema/index.ts +6 -0
  237. package/src/internal/json-schema/json-schema-normalize.ts +109 -0
  238. package/src/internal/json-schema/json-schema-type.ts +403 -0
  239. package/src/internal/object/accessors.ts +115 -0
  240. package/src/internal/object/common.ts +76 -0
  241. package/src/internal/object/create.test.ts +118 -0
  242. package/src/internal/object/create.ts +96 -0
  243. package/src/internal/object/deleted.ts +19 -0
  244. package/src/internal/object/entity.ts +204 -0
  245. package/src/internal/object/expando.ts +21 -0
  246. package/src/internal/object/ids.ts +12 -0
  247. package/src/internal/object/index.ts +20 -0
  248. package/src/internal/object/inspect.ts +48 -0
  249. package/src/internal/object/json-serializer.test.ts +99 -0
  250. package/src/internal/object/json-serializer.ts +225 -0
  251. package/src/internal/object/meta.ts +62 -0
  252. package/src/internal/object/model.ts +170 -0
  253. package/src/internal/object/relation.ts +24 -0
  254. package/src/internal/object/schema-validator.test.ts +186 -0
  255. package/src/internal/object/schema-validator.ts +241 -0
  256. package/src/internal/object/typed-object.test.ts +34 -0
  257. package/src/internal/object/typed-object.ts +81 -0
  258. package/src/internal/object/typed-relation.ts +85 -0
  259. package/src/internal/object/typename.ts +61 -0
  260. package/src/internal/object/version.ts +22 -0
  261. package/src/internal/projection/compose.test.ts +43 -0
  262. package/src/internal/projection/compose.ts +36 -0
  263. package/src/internal/projection/index.ts +5 -0
  264. package/src/internal/proxy/handler.test.ts +163 -0
  265. package/src/internal/proxy/reactive-object.ts +108 -0
  266. package/src/internal/proxy/schema.test.ts +136 -0
  267. package/src/internal/proxy/typed-handler.test.ts +102 -0
  268. package/src/internal/proxy/typed-handler.ts +228 -0
  269. package/src/internal/proxy/typed-object.test.ts +100 -0
  270. package/src/internal/query/index.ts +5 -0
  271. package/src/internal/query/query.ts +23 -0
  272. package/src/internal/ref/index.ts +6 -0
  273. package/src/internal/ref/ref-array.ts +39 -0
  274. package/src/internal/ref/ref.test.ts +100 -0
  275. package/src/internal/ref/ref.ts +521 -0
  276. package/src/internal/schema/echo-schema.ts +383 -0
  277. package/src/internal/schema/index.ts +10 -0
  278. package/src/internal/schema/manipulation.ts +86 -0
  279. package/src/internal/schema/runtime-schema-registry.ts +78 -0
  280. package/src/internal/schema/snapshot.ts +25 -0
  281. package/src/internal/schema/stored-schema.ts +26 -0
  282. package/src/internal/testing/index.ts +6 -0
  283. package/src/internal/testing/types.ts +211 -0
  284. package/src/internal/testing/utils.ts +54 -0
  285. package/src/internal/types/index.ts +6 -0
  286. package/src/internal/types/types.test.ts +48 -0
  287. package/src/internal/types/types.ts +176 -0
  288. package/src/internal/types/util.ts +9 -0
  289. package/src/query/index.ts +2 -1
  290. package/src/query/{dsl.test.ts → query.test.ts} +41 -2
  291. package/src/query/{dsl.ts → query.ts} +170 -32
  292. package/src/query/tag.ts +35 -0
  293. package/src/test/api.test.ts +17 -10
  294. package/src/testing/echo-schema.ts +39 -0
  295. package/src/testing/index.ts +2 -0
  296. package/src/testing/types.ts +1 -1
  297. package/dist/lib/browser/chunk-EUA7CM23.mjs +0 -619
  298. package/dist/lib/browser/chunk-EUA7CM23.mjs.map +0 -7
  299. package/dist/lib/node-esm/chunk-IV6BWGHK.mjs +0 -619
  300. package/dist/lib/node-esm/chunk-IV6BWGHK.mjs.map +0 -7
  301. package/dist/types/src/experimental/database.d.ts +0 -8
  302. package/dist/types/src/experimental/database.d.ts.map +0 -1
  303. package/dist/types/src/experimental/index.d.ts +0 -1
  304. package/dist/types/src/experimental/index.d.ts.map +0 -1
  305. package/dist/types/src/experimental/queue.d.ts +0 -8
  306. package/dist/types/src/experimental/queue.d.ts.map +0 -1
  307. package/dist/types/src/experimental/space.d.ts +0 -8
  308. package/dist/types/src/experimental/space.d.ts.map +0 -1
  309. package/dist/types/src/query/dsl.d.ts.map +0 -1
  310. package/dist/types/src/query/dsl.test.d.ts +0 -2
  311. package/dist/types/src/query/dsl.test.d.ts.map +0 -1
  312. package/src/experimental/database.ts +0 -11
  313. package/src/experimental/index.ts +0 -7
  314. package/src/experimental/queue.ts +0 -11
  315. package/src/experimental/space.ts +0 -11
@@ -2,20 +2,52 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Schema } from 'effect';
6
- import type { Simplify } from 'effect/Schema';
5
+ import type * as EffectArray from 'effect/Array';
6
+ import * as Match from 'effect/Match';
7
+ import * as Schema from 'effect/Schema';
7
8
 
8
9
  import { raise } from '@dxos/debug';
9
10
  import { type ForeignKey, type QueryAST } from '@dxos/echo-protocol';
10
- import { getTypeReference } from '@dxos/echo-schema';
11
11
  import { assertArgument } from '@dxos/invariant';
12
12
  import { DXN, ObjectId } from '@dxos/keys';
13
13
 
14
+ import { getTypeReference } from '../internal';
15
+ import type * as Obj from '../Obj';
14
16
  import * as Ref from '../Ref';
15
17
  import type * as Type from '../Type';
16
18
 
17
19
  // TODO(dmaretskyi): Split up into interfaces for objects and relations so they can have separate verbs.
18
20
  // TODO(dmaretskyi): Undirected relation traversals.
21
+ // TODO(wittjosiah): Make Filter & Query pipeable.
22
+
23
+ export interface Order<T> {
24
+ // TODO(dmaretskyi): See new effect-schema approach to variance.
25
+ '~Order': { value: T };
26
+
27
+ ast: QueryAST.Order;
28
+ }
29
+
30
+ class OrderClass implements Order<any> {
31
+ private static variance: Order<any>['~Order'] = {} as Order<any>['~Order'];
32
+
33
+ static is(value: unknown): value is Order<any> {
34
+ return typeof value === 'object' && value !== null && '~Order' in value;
35
+ }
36
+
37
+ constructor(public readonly ast: QueryAST.Order) {}
38
+
39
+ '~Order' = OrderClass.variance;
40
+ }
41
+
42
+ export namespace Order {
43
+ export const natural: Order<any> = new OrderClass({ kind: 'natural' });
44
+ export const property = <T>(property: keyof T & string, direction: QueryAST.OrderDirection): Order<T> =>
45
+ new OrderClass({
46
+ kind: 'property',
47
+ property,
48
+ direction,
49
+ });
50
+ }
19
51
 
20
52
  export interface Query<T> {
21
53
  // TODO(dmaretskyi): See new effect-schema approach to variance.
@@ -33,10 +65,18 @@ export interface Query<T> {
33
65
 
34
66
  /**
35
67
  * Traverse an outgoing reference.
36
- * @param key - Property path inside T that is a reference.
68
+ * @param key - Property path inside T that is a reference or optional reference.
37
69
  * @returns Query for the target of the reference.
38
70
  */
39
- reference<K extends RefPropKey<T>>(key: K): Query<T[K] extends Ref.Any ? Ref.Target<T[K]> : never>;
71
+ reference<K extends RefPropKey<T>>(
72
+ key: K,
73
+ ): Query<
74
+ T[K] extends Ref.Any
75
+ ? Ref.Target<T[K]>
76
+ : T[K] extends Ref.Any | undefined
77
+ ? Ref.Target<Exclude<T[K], undefined>>
78
+ : never
79
+ >;
40
80
 
41
81
  /**
42
82
  * Find objects referencing this object.
@@ -47,7 +87,7 @@ export interface Query<T> {
47
87
  // TODO(dmaretskyi): any way to enforce `Ref.Target<Schema.Schema.Type<S>[key]> == T`?
48
88
  // TODO(dmaretskyi): Ability to go through arrays of references.
49
89
  referencedBy<S extends Schema.Schema.All>(
50
- target: S,
90
+ target: S | string,
51
91
  key: RefPropKey<Schema.Schema.Type<S>>,
52
92
  ): Query<Schema.Schema.Type<S>>;
53
93
 
@@ -58,7 +98,7 @@ export interface Query<T> {
58
98
  * @param predicates - Predicates to filter the relation objects.
59
99
  */
60
100
  sourceOf<S extends Schema.Schema.All>(
61
- relation: S,
101
+ relation: S | string,
62
102
  predicates?: Filter.Props<Schema.Schema.Type<S>>,
63
103
  ): Query<Schema.Schema.Type<S>>;
64
104
 
@@ -69,7 +109,7 @@ export interface Query<T> {
69
109
  * @param predicates - Predicates to filter the relation objects.
70
110
  */
71
111
  targetOf<S extends Schema.Schema.All>(
72
- relation: S,
112
+ relation: S | string,
73
113
  predicates?: Filter.Props<Schema.Schema.Type<S>>,
74
114
  ): Query<Schema.Schema.Type<S>>;
75
115
 
@@ -85,6 +125,14 @@ export interface Query<T> {
85
125
  */
86
126
  target(): Query<Type.Relation.Target<T>>;
87
127
 
128
+ /**
129
+ * Order the query results.
130
+ * Orders are specified in priority order. The first order will be applied first, etc.
131
+ * @param order - Order to sort the results.
132
+ * @returns Query for the ordered results.
133
+ */
134
+ orderBy(...order: EffectArray.NonEmptyArray<Order<T>>): Query<T>;
135
+
88
136
  /**
89
137
  * Add options to a query.
90
138
  */
@@ -94,6 +142,9 @@ export interface Query<T> {
94
142
  interface QueryAPI {
95
143
  is(value: unknown): value is Query.Any;
96
144
 
145
+ /** Construct a query from an ast. */
146
+ fromAst(ast: QueryAST.Query): Query<any>;
147
+
97
148
  /**
98
149
  * Select objects based on a filter.
99
150
  * @param filter - Filter to select the objects.
@@ -110,7 +161,7 @@ interface QueryAPI {
110
161
  * Shorthand for: `Query.select(Filter.type(schema, predicates))`.
111
162
  */
112
163
  type<S extends Schema.Schema.All>(
113
- schema: S,
164
+ schema: S | string,
114
165
  predicates?: Filter.Props<Schema.Schema.Type<S>>,
115
166
  ): Query<Schema.Schema.Type<S>>;
116
167
 
@@ -156,6 +207,9 @@ type Intersection<Types extends readonly unknown[]> = Types extends [infer First
156
207
  interface FilterAPI {
157
208
  is(value: unknown): value is Filter<any>;
158
209
 
210
+ /** Construct a filter from an ast. */
211
+ fromAst(ast: QueryAST.Filter): Filter<any>;
212
+
159
213
  /**
160
214
  * Filter that matches all objects.
161
215
  */
@@ -176,7 +230,7 @@ interface FilterAPI {
176
230
  * Filter by type.
177
231
  */
178
232
  type<S extends Schema.Schema.All>(
179
- schema: S,
233
+ schema: S | string,
180
234
  props?: Filter.Props<Schema.Schema.Type<S>>,
181
235
  ): Filter<Schema.Schema.Type<S>>;
182
236
 
@@ -190,12 +244,15 @@ interface FilterAPI {
190
244
  */
191
245
  typeDXN(dxn: DXN): Filter<any>;
192
246
 
247
+ /**
248
+ * Filter by tag.
249
+ */
250
+ tag(tag: string): Filter<Obj.Any>;
251
+
193
252
  /**
194
253
  * Filter by properties.
195
- *
196
- * INTERNAL API: Do not use.
197
254
  */
198
- _props<T>(props: Filter.Props<T>): Filter<T>;
255
+ props<T>(props: Filter.Props<T>): Filter<T>;
199
256
 
200
257
  /**
201
258
  * Full-text or vector search.
@@ -252,6 +309,12 @@ interface FilterAPI {
252
309
  */
253
310
  in<T>(...values: T[]): Filter<T>;
254
311
 
312
+ /**
313
+ * Predicate for an array property to contain the provided value.
314
+ * @param value - Value to check against.
315
+ */
316
+ contains<T>(value: T): Filter<T[]>;
317
+
255
318
  /**
256
319
  * Predicate for property to be in the provided range.
257
320
  * @param from - Start of the range (inclusive).
@@ -287,9 +350,9 @@ export declare namespace Filter {
287
350
 
288
351
  type Type<F extends Any> = F extends Filter<infer T> ? T : never;
289
352
 
290
- type And<FS extends readonly Any[]> = Simplify<Intersection<{ [K in keyof FS]: Type<FS[K]> }>>;
353
+ type And<FS extends readonly Any[]> = Schema.Simplify<Intersection<{ [K in keyof FS]: Type<FS[K]> }>>;
291
354
 
292
- type Or<FS extends readonly Any[]> = Simplify<{ [K in keyof FS]: Type<FS[K]> }[number]>;
355
+ type Or<FS extends readonly Any[]> = Schema.Simplify<{ [K in keyof FS]: Type<FS[K]> }[number]>;
293
356
  }
294
357
 
295
358
  class FilterClass implements Filter<any> {
@@ -299,6 +362,10 @@ class FilterClass implements Filter<any> {
299
362
  return typeof value === 'object' && value !== null && '~Filter' in value;
300
363
  }
301
364
 
365
+ static fromAst(ast: QueryAST.Filter): Filter<any> {
366
+ return new FilterClass(ast);
367
+ }
368
+
302
369
  static everything(): FilterClass {
303
370
  return new FilterClass({
304
371
  type: 'object',
@@ -329,6 +396,7 @@ class FilterClass implements Filter<any> {
329
396
  static ids(...ids: ObjectId[]): Filter<any> {
330
397
  assertArgument(
331
398
  ids.every((id) => ObjectId.isValid(id)),
399
+ 'ids',
332
400
  'ids must be valid',
333
401
  );
334
402
 
@@ -345,10 +413,10 @@ class FilterClass implements Filter<any> {
345
413
  }
346
414
 
347
415
  static type<S extends Schema.Schema.All>(
348
- schema: S,
416
+ schema: S | string,
349
417
  props?: Filter.Props<Schema.Schema.Type<S>>,
350
418
  ): Filter<Schema.Schema.Type<S>> {
351
- const dxn = getTypeReference(schema)?.toDXN() ?? raise(new TypeError('Schema has no DXN'));
419
+ const dxn = getTypeDXNFromSpecifier(schema);
352
420
  return new FilterClass({
353
421
  type: 'object',
354
422
  typename: dxn.toString(),
@@ -357,7 +425,7 @@ class FilterClass implements Filter<any> {
357
425
  }
358
426
 
359
427
  static typename(typename: string): Filter<any> {
360
- assertArgument(!typename.startsWith('dxn:'), 'Typename must no be qualified');
428
+ assertArgument(!typename.startsWith('dxn:'), 'typename', 'Typename must no be qualified');
361
429
  return new FilterClass({
362
430
  type: 'object',
363
431
  typename: DXN.fromTypename(typename).toString(),
@@ -373,10 +441,14 @@ class FilterClass implements Filter<any> {
373
441
  });
374
442
  }
375
443
 
376
- /**
377
- * @internal
378
- */
379
- static _props<T>(props: Filter.Props<T>): Filter<T> {
444
+ static tag(tag: string): Filter<any> {
445
+ return new FilterClass({
446
+ type: 'tag',
447
+ tag,
448
+ });
449
+ }
450
+
451
+ static props<T>(props: Filter.Props<T>): Filter<T> {
380
452
  return new FilterClass({
381
453
  type: 'object',
382
454
  typename: null,
@@ -392,8 +464,11 @@ class FilterClass implements Filter<any> {
392
464
  });
393
465
  }
394
466
 
395
- static foreignKeys<S extends Schema.Schema.All>(schema: S, keys: ForeignKey[]): Filter<Schema.Schema.Type<S>> {
396
- const dxn = getTypeReference(schema)?.toDXN() ?? raise(new TypeError('Schema has no DXN'));
467
+ static foreignKeys<S extends Schema.Schema.All>(
468
+ schema: S | string,
469
+ keys: ForeignKey[],
470
+ ): Filter<Schema.Schema.Type<S>> {
471
+ const dxn = getTypeDXNFromSpecifier(schema);
397
472
  return new FilterClass({
398
473
  type: 'object',
399
474
  typename: dxn.toString(),
@@ -461,6 +536,13 @@ class FilterClass implements Filter<any> {
461
536
  });
462
537
  }
463
538
 
539
+ static contains<T>(value: T): Filter<T[]> {
540
+ return new FilterClass({
541
+ type: 'contains',
542
+ value,
543
+ });
544
+ }
545
+
464
546
  static between<T>(from: T, to: T): Filter<T> {
465
547
  return new FilterClass({
466
548
  type: 'range',
@@ -506,7 +588,11 @@ type RefPropKey<T> = keyof T & string;
506
588
  const propsFilterToAst = (predicates: Filter.Props<any>): Pick<QueryAST.FilterObject, 'id' | 'props'> => {
507
589
  let idFilter: readonly ObjectId[] | undefined;
508
590
  if ('id' in predicates) {
509
- assertArgument(typeof predicates.id === 'string' || Array.isArray(predicates.id), 'invalid id filter');
591
+ assertArgument(
592
+ typeof predicates.id === 'string' || Array.isArray(predicates.id),
593
+ 'predicates.id',
594
+ 'invalid id filter',
595
+ );
510
596
  idFilter = typeof predicates.id === 'string' ? [predicates.id] : predicates.id;
511
597
  Schema.Array(ObjectId).pipe(Schema.validateSync)(idFilter);
512
598
  }
@@ -516,11 +602,37 @@ const propsFilterToAst = (predicates: Filter.Props<any>): Pick<QueryAST.FilterOb
516
602
  props: Object.fromEntries(
517
603
  Object.entries(predicates)
518
604
  .filter(([prop, _value]) => prop !== 'id')
519
- .map(([prop, predicate]) => [prop, Filter.is(predicate) ? predicate.ast : Filter.eq(predicate).ast]),
605
+ .map(([prop, predicate]) => [prop, processPredicate(predicate)]),
520
606
  ) as Record<string, QueryAST.Filter>,
521
607
  };
522
608
  };
523
609
 
610
+ const processPredicate = (predicate: any): QueryAST.Filter => {
611
+ return Match.value(predicate).pipe(
612
+ Match.withReturnType<QueryAST.Filter>(),
613
+ Match.when(Filter.is, (predicate) => predicate.ast),
614
+ // TODO(wittjosiah): Add support for array predicates.
615
+ Match.when(Array.isArray, (_predicate) => {
616
+ throw new Error('Array predicates are not yet supported.');
617
+ }),
618
+ Match.when(
619
+ (predicate: any) => !Ref.isRef(predicate) && typeof predicate === 'object' && predicate !== null,
620
+ (predicate) => {
621
+ const nestedProps = Object.fromEntries(
622
+ Object.entries(predicate).map(([key, value]) => [key, processPredicate(value)]),
623
+ );
624
+
625
+ return {
626
+ type: 'object',
627
+ typename: null,
628
+ props: nestedProps,
629
+ };
630
+ },
631
+ ),
632
+ Match.orElse((value) => Filter.eq(value).ast),
633
+ );
634
+ };
635
+
524
636
  class QueryClass implements Query<any> {
525
637
  private static variance: Query<any>['~Query'] = {} as Query<any>['~Query'];
526
638
 
@@ -528,6 +640,10 @@ class QueryClass implements Query<any> {
528
640
  return typeof value === 'object' && value !== null && '~Query' in value;
529
641
  }
530
642
 
643
+ static fromAst(ast: QueryAST.Query): Query<any> {
644
+ return new QueryClass(ast);
645
+ }
646
+
531
647
  static select<F extends Filter.Any>(filter: F): Query<Filter.Type<F>> {
532
648
  return new QueryClass({
533
649
  type: 'select',
@@ -535,7 +651,7 @@ class QueryClass implements Query<any> {
535
651
  });
536
652
  }
537
653
 
538
- static type(schema: Schema.Schema.All, predicates?: Filter.Props<unknown>): Query<any> {
654
+ static type(schema: Schema.Schema.All | string, predicates?: Filter.Props<unknown>): Query<any> {
539
655
  return new QueryClass({
540
656
  type: 'select',
541
657
  filter: FilterClass.type(schema, predicates).ast,
@@ -577,7 +693,7 @@ class QueryClass implements Query<any> {
577
693
  return new QueryClass({
578
694
  type: 'filter',
579
695
  selection: this.ast,
580
- filter: FilterClass._props(filter).ast,
696
+ filter: FilterClass.props(filter).ast,
581
697
  });
582
698
  }
583
699
  }
@@ -590,8 +706,8 @@ class QueryClass implements Query<any> {
590
706
  });
591
707
  }
592
708
 
593
- referencedBy(target: Schema.Schema.All, key: string): Query<any> {
594
- const dxn = getTypeReference(target)?.toDXN() ?? raise(new TypeError('Target schema has no DXN'));
709
+ referencedBy(target: Schema.Schema.All | string, key: string): Query<any> {
710
+ const dxn = getTypeDXNFromSpecifier(target);
595
711
  return new QueryClass({
596
712
  type: 'incoming-references',
597
713
  anchor: this.ast,
@@ -600,7 +716,7 @@ class QueryClass implements Query<any> {
600
716
  });
601
717
  }
602
718
 
603
- sourceOf(relation: Schema.Schema.All, predicates?: Filter.Props<unknown> | undefined): Query<any> {
719
+ sourceOf(relation: Schema.Schema.All | string, predicates?: Filter.Props<unknown> | undefined): Query<any> {
604
720
  return new QueryClass({
605
721
  type: 'relation',
606
722
  anchor: this.ast,
@@ -609,7 +725,7 @@ class QueryClass implements Query<any> {
609
725
  });
610
726
  }
611
727
 
612
- targetOf(relation: Schema.Schema.All, predicates?: Filter.Props<unknown> | undefined): Query<any> {
728
+ targetOf(relation: Schema.Schema.All | string, predicates?: Filter.Props<unknown> | undefined): Query<any> {
613
729
  return new QueryClass({
614
730
  type: 'relation',
615
731
  anchor: this.ast,
@@ -634,6 +750,14 @@ class QueryClass implements Query<any> {
634
750
  });
635
751
  }
636
752
 
753
+ orderBy(...order: Order<any>[]): Query<any> {
754
+ return new QueryClass({
755
+ type: 'order',
756
+ query: this.ast,
757
+ order: order.map((o) => o.ast),
758
+ });
759
+ }
760
+
637
761
  options(options: QueryAST.QueryOptions): Query<any> {
638
762
  return new QueryClass({
639
763
  type: 'options',
@@ -644,3 +768,17 @@ class QueryClass implements Query<any> {
644
768
  }
645
769
 
646
770
  export const Query: QueryAPI = QueryClass;
771
+
772
+ /**
773
+ * @param input schema or a typename string
774
+ * @return type DXN
775
+ */
776
+ const getTypeDXNFromSpecifier = (input: Schema.Schema.All | string): DXN => {
777
+ if (Schema.isSchema(input)) {
778
+ return getTypeReference(input)?.toDXN() ?? raise(new TypeError('Schema has no DXN'));
779
+ } else {
780
+ assertArgument(typeof input === 'string', 'input');
781
+ assertArgument(!input.startsWith('dxn:'), 'input');
782
+ return DXN.fromTypename(input);
783
+ }
784
+ };
@@ -0,0 +1,35 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Schema from 'effect/Schema';
6
+
7
+ export const TagInfo = Schema.Struct({
8
+ label: Schema.String,
9
+ hue: Schema.optional(Schema.String), // TODO(burdon): Color name?
10
+ });
11
+
12
+ export type TagInfo = Schema.Schema.Type<typeof TagInfo>;
13
+
14
+ export const Tag = Schema.extend(
15
+ TagInfo,
16
+ Schema.Struct({
17
+ id: Schema.String,
18
+ }),
19
+ );
20
+
21
+ export type Tag = Schema.Schema.Type<typeof Tag>;
22
+
23
+ export type TagMap = Record<string, TagInfo>;
24
+
25
+ export const sortTags = ({ label: a }: TagInfo, { label: b }: TagInfo) => a.localeCompare(b);
26
+
27
+ export const createTagList = (tags: TagMap): Tag[] =>
28
+ Object.entries(tags)
29
+ .map(([id, tag]) => ({ ...tag, id }))
30
+ .sort(sortTags);
31
+
32
+ export const findTagByLabel = (tags: Record<string, TagInfo> | undefined, name: string): Tag | undefined => {
33
+ const entry = Object.entries(tags ?? {}).find(([_, tag]) => tag.label.toLowerCase() === name.toLowerCase());
34
+ return entry ? { ...entry[1], id: entry[0] } : undefined;
35
+ };
@@ -2,13 +2,13 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Schema } from 'effect';
5
+ import * as Schema from 'effect/Schema';
6
6
  import { describe, test } from 'vitest';
7
7
 
8
8
  import { raise } from '@dxos/debug';
9
- import { FormatEnum, FormatAnnotation } from '@dxos/echo-schema';
9
+ import { FormatAnnotation, FormatEnum } from '@dxos/echo/internal';
10
10
 
11
- import { Obj, Ref, Relation, Type, type Live } from '../index';
11
+ import { type Live, Obj, Ref, Relation, Type } from '../index';
12
12
 
13
13
  namespace Testing {
14
14
  export const Organization = Schema.Struct({
@@ -151,22 +151,29 @@ describe('Experimental API review', () => {
151
151
  expect(Relation.getTarget(worksFor)).to.eq(organization);
152
152
  });
153
153
 
154
+ test('version', ({ expect }) => {
155
+ const person = Obj.make(Testing.Person, { name: 'Test' });
156
+ const version = Obj.version(person);
157
+ expect(Obj.isVersion(version)).to.be.true;
158
+ expect(Obj.versionValid(version)).to.be.false;
159
+ });
160
+
154
161
  test.skip('type narrowing', () => {
155
- const a: Obj.Any | Relation.Any = null as any;
162
+ const any: Obj.Any | Relation.Any = null as any;
156
163
 
157
164
  {
158
- if (Obj.isObject(a)) {
159
- a;
165
+ if (Obj.isObject(any)) {
166
+ any;
160
167
  } else {
161
- a;
168
+ any;
162
169
  }
163
170
  }
164
171
 
165
172
  {
166
- if (Relation.isRelation(a)) {
167
- a;
173
+ if (Relation.isRelation(any)) {
174
+ any;
168
175
  } else {
169
- a;
176
+ any;
170
177
  }
171
178
  }
172
179
  });
@@ -0,0 +1,39 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { effect } from '@preact/signals-core';
6
+ import type * as Schema from 'effect/Schema';
7
+
8
+ import { registerSignalsRuntime } from '@dxos/echo-signals';
9
+ import { assertArgument } from '@dxos/invariant';
10
+
11
+ import { EchoSchema, StoredSchema, getSchemaTypename, live, toJsonSchema } from '../internal';
12
+
13
+ // NOTE: Registration is done here is this is the module that calls out to `effect`.
14
+ registerSignalsRuntime();
15
+
16
+ /**
17
+ * Create a reactive mutable schema that updates when the JSON schema is updated.
18
+ */
19
+ // TODO(dmaretskyi): Should be replaced by registration of typed object.
20
+ export const createEchoSchema = (schema: Schema.Schema.AnyNoContext): EchoSchema => {
21
+ const typename = getSchemaTypename(schema);
22
+ assertArgument(typename, 'typename', 'Schema does not have a typename.');
23
+
24
+ const echoSchema = new EchoSchema(
25
+ live(StoredSchema, {
26
+ typename,
27
+ version: '0.1.0',
28
+ jsonSchema: toJsonSchema(schema),
29
+ }),
30
+ );
31
+
32
+ // TODO(burdon): Unsubscribe is never called.
33
+ effect(() => {
34
+ const _ = echoSchema.jsonSchema;
35
+ echoSchema._invalidate();
36
+ });
37
+
38
+ return echoSchema;
39
+ };
@@ -2,4 +2,6 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ export { prepareAstForCompare, Testing as TestingDeprecated, updateCounter } from '../internal/testing';
5
6
  export * from './types';
7
+ export * from './echo-schema';
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Schema } from 'effect';
5
+ import * as Schema from 'effect/Schema';
6
6
 
7
7
  import { Type } from '..';
8
8