@dxos/echo 0.8.4-main.c1de068 → 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
@@ -0,0 +1,228 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { type InspectOptionsStylized } from 'node:util';
6
+
7
+ import * as Schema from 'effect/Schema';
8
+ import * as SchemaAST from 'effect/SchemaAST';
9
+
10
+ import { inspectCustom } from '@dxos/debug';
11
+ import { type GenericSignal, compositeRuntime } from '@dxos/echo-signals/runtime';
12
+ import { invariant } from '@dxos/invariant';
13
+ import {
14
+ ReactiveArray,
15
+ type ReactiveHandler,
16
+ createProxy,
17
+ defineHiddenProperty,
18
+ isValidProxyTarget,
19
+ objectData,
20
+ symbolIsProxy,
21
+ } from '@dxos/live-object';
22
+
23
+ import { getSchemaDXN } from '../ast';
24
+ import { DeletedId, SchemaId, SchemaValidator, TypeId } from '../object';
25
+
26
+ const symbolSignal = Symbol('signal');
27
+ const symbolPropertySignal = Symbol('property-signal');
28
+
29
+ type ProxyTarget = {
30
+ /**
31
+ * Typename or type DXN.
32
+ */
33
+ [TypeId]: string;
34
+
35
+ /**
36
+ * Schema for the root.
37
+ */
38
+ [SchemaId]: Schema.Schema.AnyNoContext;
39
+
40
+ /**
41
+ * For get and set operations on value properties.
42
+ */
43
+ // TODO(dmaretskyi): Turn into a map of signals per-field.
44
+ [symbolSignal]: GenericSignal;
45
+
46
+ /**
47
+ * For modifying the structure of the object.
48
+ */
49
+ [symbolPropertySignal]: GenericSignal;
50
+ } & ({ [key: keyof any]: any } | any[]);
51
+
52
+ /**
53
+ * Typed in-memory reactive store (with Schema).
54
+ */
55
+ export class TypedReactiveHandler implements ReactiveHandler<ProxyTarget> {
56
+ public static readonly instance: ReactiveHandler<any> = new TypedReactiveHandler();
57
+
58
+ readonly _proxyMap = new WeakMap<object, any>();
59
+
60
+ private constructor() {}
61
+
62
+ init(target: ProxyTarget): void {
63
+ invariant(typeof target === 'object' && target !== null);
64
+ invariant(SchemaId in target, 'Schema is not defined for the target');
65
+
66
+ if (!(symbolSignal in target)) {
67
+ defineHiddenProperty(target, symbolSignal, compositeRuntime.createSignal());
68
+ defineHiddenProperty(target, symbolPropertySignal, compositeRuntime.createSignal());
69
+ }
70
+
71
+ defineHiddenProperty(target, DeletedId, false);
72
+
73
+ for (const key of Object.getOwnPropertyNames(target)) {
74
+ const descriptor = Object.getOwnPropertyDescriptor(target, key)!;
75
+ if (descriptor.get) {
76
+ // Ignore getters.
77
+ continue;
78
+ }
79
+
80
+ // Array reactivity is already handled by the schema validator.
81
+ }
82
+
83
+ // Maybe have been set by `create`.
84
+ Object.defineProperty(target, inspectCustom, {
85
+ enumerable: false,
86
+ configurable: true,
87
+ value: this._inspect.bind(target),
88
+ });
89
+ }
90
+
91
+ get(target: ProxyTarget, prop: string | symbol, receiver: any): any {
92
+ switch (prop) {
93
+ case objectData: {
94
+ target[symbolSignal].notifyRead();
95
+ return toJSON(target);
96
+ }
97
+ }
98
+
99
+ // Handle getter properties. Will not subscribe the value signal.
100
+ if (Object.getOwnPropertyDescriptor(target, prop)?.get) {
101
+ target[symbolPropertySignal].notifyRead();
102
+
103
+ // TODO(dmaretskyi): Turn getters into computed fields.
104
+ return Reflect.get(target, prop, receiver);
105
+ }
106
+
107
+ target[symbolSignal].notifyRead();
108
+ target[symbolPropertySignal].notifyRead();
109
+
110
+ const value = Reflect.get(target, prop, receiver);
111
+ if (isValidProxyTarget(value)) {
112
+ return createProxy(value, this);
113
+ }
114
+
115
+ return value;
116
+ }
117
+
118
+ set(target: ProxyTarget, prop: string | symbol, value: any, receiver: any): boolean {
119
+ // Convert arrays to reactive arrays on write.
120
+ if (Array.isArray(value)) {
121
+ value = ReactiveArray.from(value);
122
+ }
123
+
124
+ let result: boolean = false;
125
+ compositeRuntime.batch(() => {
126
+ const validatedValue = this._validateValue(target, prop, value);
127
+ result = Reflect.set(target, prop, validatedValue, receiver);
128
+ target[symbolSignal].notifyWrite();
129
+ });
130
+ return result;
131
+ }
132
+
133
+ ownKeys(target: ProxyTarget): ArrayLike<string | symbol> {
134
+ // Touch both signals since `set` and `delete` operations may create or remove properties.
135
+ target[symbolSignal].notifyRead();
136
+ target[symbolPropertySignal].notifyRead();
137
+ return Reflect.ownKeys(target);
138
+ }
139
+
140
+ defineProperty(target: ProxyTarget, property: string | symbol, attributes: PropertyDescriptor): boolean {
141
+ const validatedValue = this._validateValue(target, property, attributes.value);
142
+ const result = Reflect.defineProperty(target, property, {
143
+ ...attributes,
144
+ value: validatedValue,
145
+ });
146
+ target[symbolPropertySignal].notifyWrite();
147
+ return result;
148
+ }
149
+
150
+ private _validateValue(target: any, prop: string | symbol, value: any) {
151
+ const schema = SchemaValidator.getTargetPropertySchema(target, prop);
152
+ const _ = Schema.asserts(schema)(value);
153
+ if (Array.isArray(value)) {
154
+ value = new ReactiveArray(...value);
155
+ }
156
+ if (isValidProxyTarget(value)) {
157
+ setSchemaProperties(value, schema);
158
+ }
159
+
160
+ return value;
161
+ }
162
+
163
+ private _inspect(
164
+ _: number,
165
+ options: InspectOptionsStylized,
166
+ inspectFn: (value: any, options?: InspectOptionsStylized) => string,
167
+ ): string {
168
+ return `Typed ${inspectFn(this, {
169
+ ...options,
170
+ compact: true,
171
+ showHidden: false,
172
+ customInspect: false,
173
+ })}`;
174
+ }
175
+ }
176
+
177
+ /**
178
+ * @deprecated Use `Obj.toJSON` instead.
179
+ */
180
+ const toJSON = (target: ProxyTarget): any => {
181
+ return { '@type': 'TypedReactiveObject', ...target };
182
+ };
183
+
184
+ /**
185
+ * Recursively set AST on all potential proxy targets.
186
+ */
187
+ const setSchemaProperties = (obj: any, schema: Schema.Schema.AnyNoContext) => {
188
+ const schemaType = getSchemaDXN(schema);
189
+ if (schemaType != null) {
190
+ defineHiddenProperty(obj, TypeId, schemaType);
191
+ }
192
+
193
+ defineHiddenProperty(obj, SchemaId, schema);
194
+ for (const key in obj) {
195
+ if (isValidProxyTarget(obj[key])) {
196
+ const elementSchema = SchemaValidator.getTargetPropertySchema(obj, key);
197
+ if (elementSchema != null) {
198
+ setSchemaProperties(obj[key], elementSchema);
199
+ }
200
+ }
201
+ }
202
+ };
203
+
204
+ export const prepareTypedTarget = <T>(target: T, schema: Schema.Schema<T>) => {
205
+ // log.info('prepareTypedTarget', { target, schema });
206
+ if (!SchemaAST.isTypeLiteral(schema.ast)) {
207
+ throw new Error('schema has to describe an object type');
208
+ }
209
+
210
+ SchemaValidator.validateSchema(schema);
211
+ const _ = Schema.asserts(schema)(target);
212
+ makeArraysReactive(target);
213
+ setSchemaProperties(target, schema);
214
+ };
215
+
216
+ const makeArraysReactive = (target: any) => {
217
+ for (const key in target) {
218
+ if (target[symbolIsProxy]) {
219
+ continue;
220
+ }
221
+ if (Array.isArray(target[key])) {
222
+ target[key] = ReactiveArray.from(target[key]);
223
+ }
224
+ if (typeof target[key] === 'object') {
225
+ makeArraysReactive(target[key]);
226
+ }
227
+ }
228
+ };
@@ -0,0 +1,100 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import * as Schema from 'effect/Schema';
6
+ import { describe, expect, test } from 'vitest';
7
+
8
+ import { EchoObject, TypedObject, getSchema } from '..';
9
+
10
+ import { live } from './reactive-object';
11
+
12
+ const Organization = Schema.Struct({
13
+ name: Schema.String,
14
+ }).pipe(
15
+ EchoObject({
16
+ typename: 'example.com/type/Organization',
17
+ version: '0.1.0',
18
+ }),
19
+ );
20
+
21
+ interface Organization extends Schema.Schema.Type<typeof Organization> {}
22
+
23
+ const Contact = Schema.Struct(
24
+ {
25
+ name: Schema.String,
26
+ },
27
+ { key: Schema.String, value: Schema.Any },
28
+ ).pipe(
29
+ Schema.partial,
30
+ EchoObject({
31
+ typename: 'example.com/type/Contact',
32
+ version: '0.1.0',
33
+ }),
34
+ );
35
+
36
+ interface Contact extends Schema.Schema.Type<typeof Contact> {}
37
+
38
+ const TEST_ORG: Omit<Organization, 'id'> = { name: 'Test' };
39
+
40
+ describe('EchoObject class DSL', () => {
41
+ test('can get object schema', async () => {
42
+ const obj = live(Organization, TEST_ORG);
43
+ expect(getSchema(obj)).to.deep.eq(Organization);
44
+ });
45
+
46
+ describe('class options', () => {
47
+ test('can assign undefined to partial fields', async () => {
48
+ const person = live(Contact, { name: 'John' });
49
+ person.name = undefined;
50
+ person.recordField = 'hello';
51
+ expect(person.name).to.be.undefined;
52
+ expect(person.recordField).to.eq('hello');
53
+ });
54
+ });
55
+
56
+ test('record', () => {
57
+ const schema = Schema.mutable(
58
+ Schema.Struct({
59
+ meta: Schema.optional(Schema.mutable(Schema.Any)),
60
+ // NOTE: Schema.Record only supports shallow values.
61
+ // https://www.npmjs.com/package/@effect/schema#mutable-records
62
+ // meta: Schema.optional(Schema.mutable(Schema.Record({ key: Schema.String, value: Schema.Any }))),
63
+ // meta: Schema.optional(Schema.mutable(Schema.object)),
64
+ }),
65
+ );
66
+
67
+ {
68
+ const object = live(schema, {});
69
+ (object.meta ??= {}).test = 100;
70
+ expect(object.meta.test).to.eq(100);
71
+ }
72
+
73
+ {
74
+ const object = live(schema, {});
75
+ object.meta = { test: { value: 300 } };
76
+ expect(object.meta.test.value).to.eq(300);
77
+ }
78
+
79
+ {
80
+ type Test1 = Schema.Schema.Type<typeof schema>;
81
+
82
+ const object: Test1 = {};
83
+ (object.meta ??= {}).test = 100;
84
+ expect(object.meta.test).to.eq(100);
85
+ }
86
+
87
+ {
88
+ class Test2 extends TypedObject({
89
+ typename: 'dxos.org/type/FunctionTrigger',
90
+ version: '0.1.0',
91
+ })({
92
+ meta: Schema.optional(Schema.mutable(Schema.Record({ key: Schema.String, value: Schema.Any }))),
93
+ }) {}
94
+
95
+ const object = live(Test2, {});
96
+ (object.meta ??= {}).test = 100;
97
+ expect(object.meta.test).to.eq(100);
98
+ }
99
+ });
100
+ });
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './query';
@@ -0,0 +1,23 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import * as Schema from 'effect/Schema';
6
+
7
+ // TODO(wittjosiah): Remove. Use ordering in queries instead.
8
+
9
+ /** @deprecated */
10
+ const SortDirection = Schema.Union(Schema.Literal('asc'), Schema.Literal('desc'));
11
+ /** @deprecated */
12
+ export type SortDirectionType = Schema.Schema.Type<typeof SortDirection>;
13
+
14
+ /** @deprecated */
15
+ const FieldSort = Schema.Struct({
16
+ fieldId: Schema.String,
17
+ direction: SortDirection,
18
+ }).pipe(Schema.mutable);
19
+
20
+ /** @deprecated */
21
+ export interface FieldSortType extends Schema.Schema.Type<typeof FieldSort> {}
22
+ /** @deprecated */
23
+ export const FieldSortType: Schema.Schema<FieldSortType> = FieldSort;
@@ -0,0 +1,6 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export * from './ref';
6
+ export * from './ref-array';
@@ -0,0 +1,39 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { type ObjectId } from '@dxos/keys';
6
+ import { isNonNullable } from '@dxos/util';
7
+
8
+ import { type AnyEchoObject } from '../types';
9
+
10
+ import { Ref } from './ref';
11
+
12
+ /**
13
+ * Helper functions for working with arrays of refs.
14
+ */
15
+ export const RefArray = Object.freeze({
16
+ /**
17
+ * @returns all resolved targets.
18
+ */
19
+ targets: <T extends AnyEchoObject>(refs: readonly Ref<T>[]): T[] => {
20
+ return refs.map((ref) => ref.target).filter(isNonNullable);
21
+ },
22
+
23
+ /**
24
+ * Load all referenced objects.
25
+ */
26
+ loadAll: <T extends AnyEchoObject>(refs: readonly Ref<T>[]): Promise<T[]> => {
27
+ return Promise.all(refs.map((ref) => ref.load()));
28
+ },
29
+
30
+ /**
31
+ * Removes the ref with the given id.
32
+ */
33
+ removeById: (refs: Ref<AnyEchoObject>[], id: ObjectId) => {
34
+ const index = refs.findIndex(Ref.hasObjectId(id));
35
+ if (index >= 0) {
36
+ refs.splice(index, 1);
37
+ }
38
+ },
39
+ });
@@ -0,0 +1,100 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Schema from 'effect/Schema';
6
+ import { describe, expect, test } from 'vitest';
7
+
8
+ import { DXN, ObjectId } from '@dxos/keys';
9
+
10
+ import { EchoObject, create, getObjectDXN } from '../object';
11
+
12
+ import { Ref, getReferenceAst } from './ref';
13
+
14
+ const Task = Schema.Struct({
15
+ title: Schema.optional(Schema.String),
16
+ }).pipe(
17
+ EchoObject({
18
+ typename: 'example.com/type/Task',
19
+ version: '0.1.0',
20
+ }),
21
+ );
22
+
23
+ type Task = Schema.Schema.Type<typeof Task>;
24
+
25
+ const Contact = Schema.Struct({
26
+ name: Schema.String,
27
+ email: Schema.optional(Schema.String),
28
+ tasks: Schema.mutable(Schema.Array(Ref(Task))),
29
+ }).pipe(
30
+ EchoObject({
31
+ typename: 'example.com/type/Contact',
32
+ version: '0.1.0',
33
+ }),
34
+ );
35
+
36
+ type Contact = Schema.Schema.Type<typeof Contact>;
37
+
38
+ describe('Ref', () => {
39
+ test('Schema is', () => {
40
+ Ref(Contact).pipe(Schema.is)(Ref.fromDXN(DXN.parse(`dxn:echo:@:${ObjectId.random()}`)));
41
+ });
42
+
43
+ test('ref ast', () => {
44
+ const ref = Ref(Task);
45
+ expect(ref.ast._tag).toEqual('Declaration');
46
+ const refAst = getReferenceAst(ref.ast);
47
+ expect(refAst).toEqual({ typename: Task.typename, version: Task.version });
48
+ });
49
+
50
+ // TODO(dmaretskyi): Figure out how to expose this in the API.
51
+ test.skip('encode with inlined target', () => {
52
+ const task = create(Task, { title: 'Fix bugs' });
53
+ const contact = create(Contact, { name: 'John Doe', tasks: [Ref.make(task)] });
54
+
55
+ const json = JSON.parse(JSON.stringify(contact));
56
+ expect(json).toEqual({
57
+ id: contact.id,
58
+ '@type': `dxn:type:${Contact.typename}:${Contact.version}`,
59
+ '@meta': {
60
+ keys: [],
61
+ },
62
+ name: 'John Doe',
63
+ tasks: [
64
+ {
65
+ '/': getObjectDXN(task as any)!.toString(),
66
+ target: JSON.parse(JSON.stringify(task)),
67
+ },
68
+ ],
69
+ });
70
+ });
71
+
72
+ test('encode without inlining target', () => {
73
+ const task = create(Task, { title: 'Fix bugs' });
74
+ const contact = create(Contact, { name: 'John Doe', tasks: [Ref.make(task).noInline()] });
75
+
76
+ const json = JSON.parse(JSON.stringify(contact));
77
+ expect(json).toEqual({
78
+ id: contact.id,
79
+ '@type': `dxn:type:${Contact.typename}:${Contact.version}`,
80
+ '@meta': {
81
+ keys: [],
82
+ },
83
+ name: 'John Doe',
84
+ tasks: [{ '/': getObjectDXN(task)!.toString() }],
85
+ });
86
+ });
87
+
88
+ test('decode object', () => {
89
+ const id = ObjectId.random();
90
+ const contactData = {
91
+ id: ObjectId.random(),
92
+ name: 'John Doe',
93
+ tasks: [{ '/': `dxn:echo:@:${id}` }],
94
+ };
95
+
96
+ const contact = Contact.pipe(Schema.decodeUnknownSync)(contactData);
97
+ expect(Ref.isRef(contact.tasks[0])).toEqual(true);
98
+ expect(contact.tasks[0].dxn.toString()).toEqual(`dxn:echo:@:${id}`);
99
+ });
100
+ });