@dxos/echo 0.8.4-main.7ace549 → 0.8.4-main.937b3ca

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 (450) hide show
  1. package/README.md +1 -2
  2. package/dist/lib/browser/Annotation.mjs +33 -0
  3. package/dist/lib/browser/Annotation.mjs.map +7 -0
  4. package/dist/lib/browser/Database.mjs +18 -0
  5. package/dist/lib/browser/Database.mjs.map +7 -0
  6. package/dist/lib/browser/Entity.mjs +52 -0
  7. package/dist/lib/browser/Entity.mjs.map +7 -0
  8. package/dist/lib/browser/Err.mjs +11 -0
  9. package/dist/lib/browser/Err.mjs.map +7 -0
  10. package/dist/lib/browser/Filter.mjs +62 -0
  11. package/dist/lib/browser/Filter.mjs.map +7 -0
  12. package/dist/lib/browser/Format.mjs +67 -0
  13. package/dist/lib/browser/Format.mjs.map +7 -0
  14. package/dist/lib/browser/JsonSchema.mjs +20 -0
  15. package/dist/lib/browser/JsonSchema.mjs.map +7 -0
  16. package/dist/lib/browser/Key.mjs +13 -0
  17. package/dist/lib/browser/Key.mjs.map +7 -0
  18. package/dist/lib/browser/Obj.mjs +91 -0
  19. package/dist/lib/browser/Obj.mjs.map +7 -0
  20. package/dist/lib/browser/Order.mjs +13 -0
  21. package/dist/lib/browser/Order.mjs.map +7 -0
  22. package/dist/lib/browser/Query.mjs +27 -0
  23. package/dist/lib/browser/Query.mjs.map +7 -0
  24. package/dist/lib/browser/QueryResult.mjs +3 -0
  25. package/dist/lib/browser/QueryResult.mjs.map +7 -0
  26. package/dist/lib/browser/Ref.mjs +23 -0
  27. package/dist/lib/browser/Ref.mjs.map +7 -0
  28. package/dist/lib/browser/Relation.mjs +85 -0
  29. package/dist/lib/browser/Relation.mjs.map +7 -0
  30. package/dist/lib/browser/SchemaRegistry.mjs +3 -0
  31. package/dist/lib/browser/SchemaRegistry.mjs.map +7 -0
  32. package/dist/lib/browser/Tag.mjs +26 -0
  33. package/dist/lib/browser/Tag.mjs.map +7 -0
  34. package/dist/lib/browser/Type.mjs +48 -0
  35. package/dist/lib/browser/Type.mjs.map +7 -0
  36. package/dist/lib/browser/chunk-22JMFST2.mjs +24 -0
  37. package/dist/lib/browser/chunk-22JMFST2.mjs.map +7 -0
  38. package/dist/lib/browser/chunk-2SBB7OWV.mjs +250 -0
  39. package/dist/lib/browser/chunk-2SBB7OWV.mjs.map +7 -0
  40. package/dist/lib/browser/chunk-6L5HHUVU.mjs +158 -0
  41. package/dist/lib/browser/chunk-6L5HHUVU.mjs.map +7 -0
  42. package/dist/lib/browser/chunk-7STIBCP7.mjs +133 -0
  43. package/dist/lib/browser/chunk-7STIBCP7.mjs.map +7 -0
  44. package/dist/lib/browser/{chunk-7GH6RXJ3.mjs → chunk-BJPE6CIC.mjs} +1999 -1835
  45. package/dist/lib/browser/chunk-BJPE6CIC.mjs.map +7 -0
  46. package/dist/lib/browser/chunk-CGS2ULMK.mjs +11 -0
  47. package/dist/lib/browser/chunk-CGS2ULMK.mjs.map +7 -0
  48. package/dist/lib/browser/chunk-CJ5YELTO.mjs +39 -0
  49. package/dist/lib/browser/chunk-CJ5YELTO.mjs.map +7 -0
  50. package/dist/lib/browser/chunk-FPOISFQK.mjs +40 -0
  51. package/dist/lib/browser/chunk-FPOISFQK.mjs.map +7 -0
  52. package/dist/lib/browser/chunk-FRDT7RA4.mjs +403 -0
  53. package/dist/lib/browser/chunk-FRDT7RA4.mjs.map +7 -0
  54. package/dist/lib/browser/chunk-INHXFXY5.mjs +22 -0
  55. package/dist/lib/browser/chunk-INHXFXY5.mjs.map +7 -0
  56. package/dist/lib/browser/chunk-IXVWLTG7.mjs +9 -0
  57. package/dist/lib/browser/chunk-IXVWLTG7.mjs.map +7 -0
  58. package/dist/lib/browser/chunk-JMKVF2YQ.mjs +43 -0
  59. package/dist/lib/browser/chunk-JMKVF2YQ.mjs.map +7 -0
  60. package/dist/lib/browser/chunk-KQQGVHFN.mjs +143 -0
  61. package/dist/lib/browser/chunk-KQQGVHFN.mjs.map +7 -0
  62. package/dist/lib/browser/chunk-MYCCGG2T.mjs +15 -0
  63. package/dist/lib/browser/chunk-MYCCGG2T.mjs.map +7 -0
  64. package/dist/lib/browser/chunk-NOPVNWPT.mjs +204 -0
  65. package/dist/lib/browser/chunk-NOPVNWPT.mjs.map +7 -0
  66. package/dist/lib/browser/chunk-PQZW3S6L.mjs +74 -0
  67. package/dist/lib/browser/chunk-PQZW3S6L.mjs.map +7 -0
  68. package/dist/lib/browser/chunk-RK4Z4JUZ.mjs +283 -0
  69. package/dist/lib/browser/chunk-RK4Z4JUZ.mjs.map +7 -0
  70. package/dist/lib/browser/chunk-U2J7TA7K.mjs +57 -0
  71. package/dist/lib/browser/chunk-U2J7TA7K.mjs.map +7 -0
  72. package/dist/lib/browser/chunk-W5D2GWAW.mjs +98 -0
  73. package/dist/lib/browser/chunk-W5D2GWAW.mjs.map +7 -0
  74. package/dist/lib/browser/chunk-XDIUHAAX.mjs +41 -0
  75. package/dist/lib/browser/chunk-XDIUHAAX.mjs.map +7 -0
  76. package/dist/lib/browser/chunk-YKTSSMDS.mjs +69 -0
  77. package/dist/lib/browser/chunk-YKTSSMDS.mjs.map +7 -0
  78. package/dist/lib/browser/chunk-ZAGAOZVY.mjs +288 -0
  79. package/dist/lib/browser/chunk-ZAGAOZVY.mjs.map +7 -0
  80. package/dist/lib/browser/chunk-ZHXZGIXD.mjs +9 -0
  81. package/dist/lib/browser/chunk-ZHXZGIXD.mjs.map +7 -0
  82. package/dist/lib/browser/index.mjs +65 -25
  83. package/dist/lib/browser/internal/index.mjs +213 -92
  84. package/dist/lib/browser/meta.json +1 -1
  85. package/dist/lib/browser/testing/index.mjs +80 -41
  86. package/dist/lib/browser/testing/index.mjs.map +3 -3
  87. package/dist/lib/node-esm/Annotation.mjs +33 -0
  88. package/dist/lib/node-esm/Annotation.mjs.map +7 -0
  89. package/dist/lib/node-esm/Database.mjs +18 -0
  90. package/dist/lib/node-esm/Database.mjs.map +7 -0
  91. package/dist/lib/node-esm/Entity.mjs +52 -0
  92. package/dist/lib/node-esm/Entity.mjs.map +7 -0
  93. package/dist/lib/node-esm/Err.mjs +11 -0
  94. package/dist/lib/node-esm/Err.mjs.map +7 -0
  95. package/dist/lib/node-esm/Filter.mjs +62 -0
  96. package/dist/lib/node-esm/Filter.mjs.map +7 -0
  97. package/dist/lib/node-esm/Format.mjs +67 -0
  98. package/dist/lib/node-esm/Format.mjs.map +7 -0
  99. package/dist/lib/node-esm/JsonSchema.mjs +20 -0
  100. package/dist/lib/node-esm/JsonSchema.mjs.map +7 -0
  101. package/dist/lib/node-esm/Key.mjs +13 -0
  102. package/dist/lib/node-esm/Key.mjs.map +7 -0
  103. package/dist/lib/node-esm/Obj.mjs +91 -0
  104. package/dist/lib/node-esm/Obj.mjs.map +7 -0
  105. package/dist/lib/node-esm/Order.mjs +13 -0
  106. package/dist/lib/node-esm/Order.mjs.map +7 -0
  107. package/dist/lib/node-esm/Query.mjs +27 -0
  108. package/dist/lib/node-esm/Query.mjs.map +7 -0
  109. package/dist/lib/node-esm/QueryResult.mjs +3 -0
  110. package/dist/lib/node-esm/QueryResult.mjs.map +7 -0
  111. package/dist/lib/node-esm/Ref.mjs +23 -0
  112. package/dist/lib/node-esm/Ref.mjs.map +7 -0
  113. package/dist/lib/node-esm/Relation.mjs +85 -0
  114. package/dist/lib/node-esm/Relation.mjs.map +7 -0
  115. package/dist/lib/node-esm/SchemaRegistry.mjs +3 -0
  116. package/dist/lib/node-esm/SchemaRegistry.mjs.map +7 -0
  117. package/dist/lib/node-esm/Tag.mjs +26 -0
  118. package/dist/lib/node-esm/Tag.mjs.map +7 -0
  119. package/dist/lib/node-esm/Type.mjs +48 -0
  120. package/dist/lib/node-esm/Type.mjs.map +7 -0
  121. package/dist/lib/node-esm/chunk-4PNXQA64.mjs +250 -0
  122. package/dist/lib/node-esm/chunk-4PNXQA64.mjs.map +7 -0
  123. package/dist/lib/node-esm/chunk-5OBN7GZW.mjs +158 -0
  124. package/dist/lib/node-esm/chunk-5OBN7GZW.mjs.map +7 -0
  125. package/dist/lib/node-esm/chunk-AJEMYSIR.mjs +22 -0
  126. package/dist/lib/node-esm/chunk-AJEMYSIR.mjs.map +7 -0
  127. package/dist/lib/node-esm/chunk-ANLVLWME.mjs +98 -0
  128. package/dist/lib/node-esm/chunk-ANLVLWME.mjs.map +7 -0
  129. package/dist/lib/node-esm/chunk-DMR7OAFK.mjs +57 -0
  130. package/dist/lib/node-esm/chunk-DMR7OAFK.mjs.map +7 -0
  131. package/dist/lib/node-esm/chunk-FWTSPIFF.mjs +133 -0
  132. package/dist/lib/node-esm/chunk-FWTSPIFF.mjs.map +7 -0
  133. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  134. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
  135. package/dist/lib/node-esm/chunk-ILMLLM4R.mjs +204 -0
  136. package/dist/lib/node-esm/chunk-ILMLLM4R.mjs.map +7 -0
  137. package/dist/lib/node-esm/chunk-K37NA7PO.mjs +43 -0
  138. package/dist/lib/node-esm/chunk-K37NA7PO.mjs.map +7 -0
  139. package/dist/lib/node-esm/{chunk-M4B6BMD2.mjs → chunk-LT3H4JOX.mjs} +1999 -1835
  140. package/dist/lib/node-esm/chunk-LT3H4JOX.mjs.map +7 -0
  141. package/dist/lib/node-esm/chunk-MOLNWFNL.mjs +9 -0
  142. package/dist/lib/node-esm/chunk-MOLNWFNL.mjs.map +7 -0
  143. package/dist/lib/node-esm/chunk-MOWUEW5P.mjs +15 -0
  144. package/dist/lib/node-esm/chunk-MOWUEW5P.mjs.map +7 -0
  145. package/dist/lib/node-esm/chunk-NBWL7UCZ.mjs +40 -0
  146. package/dist/lib/node-esm/chunk-NBWL7UCZ.mjs.map +7 -0
  147. package/dist/lib/node-esm/chunk-NRN3ZW2T.mjs +143 -0
  148. package/dist/lib/node-esm/chunk-NRN3ZW2T.mjs.map +7 -0
  149. package/dist/lib/node-esm/chunk-QLI2EIJ2.mjs +41 -0
  150. package/dist/lib/node-esm/chunk-QLI2EIJ2.mjs.map +7 -0
  151. package/dist/lib/node-esm/chunk-QYR67VBV.mjs +288 -0
  152. package/dist/lib/node-esm/chunk-QYR67VBV.mjs.map +7 -0
  153. package/dist/lib/node-esm/chunk-UKGVOINP.mjs +9 -0
  154. package/dist/lib/node-esm/chunk-UKGVOINP.mjs.map +7 -0
  155. package/dist/lib/node-esm/chunk-W6QIEBTQ.mjs +403 -0
  156. package/dist/lib/node-esm/chunk-W6QIEBTQ.mjs.map +7 -0
  157. package/dist/lib/node-esm/chunk-XHJRMQZD.mjs +69 -0
  158. package/dist/lib/node-esm/chunk-XHJRMQZD.mjs.map +7 -0
  159. package/dist/lib/node-esm/chunk-Y75VU7LB.mjs +74 -0
  160. package/dist/lib/node-esm/chunk-Y75VU7LB.mjs.map +7 -0
  161. package/dist/lib/node-esm/chunk-YOLH5KS4.mjs +283 -0
  162. package/dist/lib/node-esm/chunk-YOLH5KS4.mjs.map +7 -0
  163. package/dist/lib/node-esm/chunk-YQ2NWGL5.mjs +39 -0
  164. package/dist/lib/node-esm/chunk-YQ2NWGL5.mjs.map +7 -0
  165. package/dist/lib/node-esm/chunk-ZBB67AKD.mjs +24 -0
  166. package/dist/lib/node-esm/chunk-ZBB67AKD.mjs.map +7 -0
  167. package/dist/lib/node-esm/index.mjs +65 -25
  168. package/dist/lib/node-esm/internal/index.mjs +213 -92
  169. package/dist/lib/node-esm/meta.json +1 -1
  170. package/dist/lib/node-esm/testing/index.mjs +80 -41
  171. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  172. package/dist/types/src/Annotation.d.ts +1 -1
  173. package/dist/types/src/Annotation.d.ts.map +1 -1
  174. package/dist/types/src/Database.d.ts +117 -60
  175. package/dist/types/src/Database.d.ts.map +1 -1
  176. package/dist/types/src/Entity.d.ts +111 -5
  177. package/dist/types/src/Entity.d.ts.map +1 -1
  178. package/dist/types/src/Entity.test.d.ts +2 -0
  179. package/dist/types/src/Entity.test.d.ts.map +1 -0
  180. package/dist/types/src/{errors.d.ts → Err.d.ts} +13 -17
  181. package/dist/types/src/Err.d.ts.map +1 -0
  182. package/dist/types/src/Filter.d.ts +120 -0
  183. package/dist/types/src/Filter.d.ts.map +1 -0
  184. package/dist/types/src/Format.d.ts.map +1 -1
  185. package/dist/types/src/Hypergraph.d.ts +60 -0
  186. package/dist/types/src/Hypergraph.d.ts.map +1 -0
  187. package/dist/types/src/Obj.d.ts +268 -76
  188. package/dist/types/src/Obj.d.ts.map +1 -1
  189. package/dist/types/src/Obj.test.d.ts +2 -0
  190. package/dist/types/src/Obj.test.d.ts.map +1 -0
  191. package/dist/types/src/Order.d.ts +16 -0
  192. package/dist/types/src/Order.d.ts.map +1 -0
  193. package/dist/types/src/{query/query.d.ts → Query.d.ts} +53 -50
  194. package/dist/types/src/Query.d.ts.map +1 -0
  195. package/dist/types/src/Query.test.d.ts +2 -0
  196. package/dist/types/src/Query.test.d.ts.map +1 -0
  197. package/dist/types/src/QueryResult.d.ts +80 -0
  198. package/dist/types/src/QueryResult.d.ts.map +1 -0
  199. package/dist/types/src/Ref.d.ts +9 -7
  200. package/dist/types/src/Ref.d.ts.map +1 -1
  201. package/dist/types/src/Relation.d.ts +235 -18
  202. package/dist/types/src/Relation.d.ts.map +1 -1
  203. package/dist/types/src/Relation.test.d.ts +2 -0
  204. package/dist/types/src/Relation.test.d.ts.map +1 -0
  205. package/dist/types/src/SchemaRegistry.d.ts +84 -0
  206. package/dist/types/src/SchemaRegistry.d.ts.map +1 -0
  207. package/dist/types/src/Tag.d.ts +6 -6
  208. package/dist/types/src/Tag.d.ts.map +1 -1
  209. package/dist/types/src/Type.d.ts +213 -50
  210. package/dist/types/src/Type.d.ts.map +1 -1
  211. package/dist/types/src/Type.test.d.ts +2 -0
  212. package/dist/types/src/Type.test.d.ts.map +1 -0
  213. package/dist/types/src/index.d.ts +8 -2
  214. package/dist/types/src/index.d.ts.map +1 -1
  215. package/dist/types/src/internal/annotations/annotations.d.ts +23 -27
  216. package/dist/types/src/internal/annotations/annotations.d.ts.map +1 -1
  217. package/dist/types/src/internal/annotations/util.d.ts +1 -0
  218. package/dist/types/src/internal/annotations/util.d.ts.map +1 -1
  219. package/dist/types/src/internal/api/annotations.d.ts +23 -0
  220. package/dist/types/src/internal/api/annotations.d.ts.map +1 -0
  221. package/dist/types/src/internal/api/entity.d.ts +13 -0
  222. package/dist/types/src/internal/api/entity.d.ts.map +1 -0
  223. package/dist/types/src/internal/api/index.d.ts +15 -0
  224. package/dist/types/src/internal/api/index.d.ts.map +1 -0
  225. package/dist/types/src/internal/api/meta.d.ts +42 -0
  226. package/dist/types/src/internal/api/meta.d.ts.map +1 -0
  227. package/dist/types/src/internal/api/sorting.d.ts +24 -0
  228. package/dist/types/src/internal/api/sorting.d.ts.map +1 -0
  229. package/dist/types/src/internal/api/version.d.ts +42 -0
  230. package/dist/types/src/internal/api/version.d.ts.map +1 -0
  231. package/dist/types/src/internal/entities/entity.d.ts +13 -3
  232. package/dist/types/src/internal/entities/entity.d.ts.map +1 -1
  233. package/dist/types/src/internal/entities/index.d.ts +1 -1
  234. package/dist/types/src/internal/entities/index.d.ts.map +1 -1
  235. package/dist/types/src/internal/entities/model.d.ts +14 -7
  236. package/dist/types/src/internal/entities/model.d.ts.map +1 -1
  237. package/dist/types/src/internal/entities/object.d.ts +8 -1
  238. package/dist/types/src/internal/entities/object.d.ts.map +1 -1
  239. package/dist/types/src/internal/entities/relation.d.ts +8 -1
  240. package/dist/types/src/internal/entities/relation.d.ts.map +1 -1
  241. package/dist/types/src/internal/formats/format.d.ts +4 -4
  242. package/dist/types/src/internal/formats/format.d.ts.map +1 -1
  243. package/dist/types/src/internal/formats/select.d.ts +5 -3
  244. package/dist/types/src/internal/formats/select.d.ts.map +1 -1
  245. package/dist/types/src/internal/formats/string.d.ts +4 -0
  246. package/dist/types/src/internal/formats/string.d.ts.map +1 -1
  247. package/dist/types/src/internal/formats/types.d.ts +6 -2
  248. package/dist/types/src/internal/formats/types.d.ts.map +1 -1
  249. package/dist/types/src/internal/index.d.ts +2 -1
  250. package/dist/types/src/internal/index.d.ts.map +1 -1
  251. package/dist/types/src/internal/json-schema/json-schema.d.ts.map +1 -1
  252. package/dist/types/src/internal/object/clone.d.ts +8 -0
  253. package/dist/types/src/internal/object/clone.d.ts.map +1 -0
  254. package/dist/types/src/internal/object/create-object.d.ts +1 -1
  255. package/dist/types/src/internal/object/index.d.ts +3 -0
  256. package/dist/types/src/internal/object/index.d.ts.map +1 -1
  257. package/dist/types/src/internal/object/json-serializer.d.ts +13 -7
  258. package/dist/types/src/internal/object/json-serializer.d.ts.map +1 -1
  259. package/dist/types/src/internal/object/schema-validator.d.ts +1 -14
  260. package/dist/types/src/internal/object/schema-validator.d.ts.map +1 -1
  261. package/dist/types/src/internal/object/set-value.d.ts +7 -0
  262. package/dist/types/src/internal/object/set-value.d.ts.map +1 -0
  263. package/dist/types/src/internal/object/set-value.test.d.ts +2 -0
  264. package/dist/types/src/internal/object/set-value.test.d.ts.map +1 -0
  265. package/dist/types/src/internal/object/snapshot.d.ts +6 -0
  266. package/dist/types/src/internal/object/snapshot.d.ts.map +1 -0
  267. package/dist/types/src/internal/object/typed-object.d.ts +7 -13
  268. package/dist/types/src/internal/object/typed-object.d.ts.map +1 -1
  269. package/dist/types/src/internal/proxy/change-context.d.ts +55 -0
  270. package/dist/types/src/internal/proxy/change-context.d.ts.map +1 -0
  271. package/dist/types/src/internal/proxy/change.test.d.ts +2 -0
  272. package/dist/types/src/internal/proxy/change.test.d.ts.map +1 -0
  273. package/dist/types/src/internal/proxy/define-hidden-property.d.ts +5 -0
  274. package/dist/types/src/internal/proxy/define-hidden-property.d.ts.map +1 -0
  275. package/dist/types/src/internal/proxy/errors.d.ts +19 -0
  276. package/dist/types/src/internal/proxy/errors.d.ts.map +1 -0
  277. package/dist/types/src/internal/proxy/event-batch.d.ts +10 -0
  278. package/dist/types/src/internal/proxy/event-batch.d.ts.map +1 -0
  279. package/dist/types/src/internal/proxy/index.d.ts +11 -0
  280. package/dist/types/src/internal/proxy/index.d.ts.map +1 -1
  281. package/dist/types/src/internal/proxy/json-serializer.d.ts +6 -0
  282. package/dist/types/src/internal/proxy/json-serializer.d.ts.map +1 -0
  283. package/dist/types/src/internal/proxy/make-object.d.ts +2 -4
  284. package/dist/types/src/internal/proxy/make-object.d.ts.map +1 -1
  285. package/dist/types/src/internal/proxy/ownership.d.ts +57 -0
  286. package/dist/types/src/internal/proxy/ownership.d.ts.map +1 -0
  287. package/dist/types/src/internal/proxy/proxy-types.d.ts +18 -0
  288. package/dist/types/src/internal/proxy/proxy-types.d.ts.map +1 -0
  289. package/dist/types/src/internal/proxy/proxy-utils.d.ts +47 -0
  290. package/dist/types/src/internal/proxy/proxy-utils.d.ts.map +1 -0
  291. package/dist/types/src/internal/proxy/reactive-array.d.ts +8 -0
  292. package/dist/types/src/internal/proxy/reactive-array.d.ts.map +1 -0
  293. package/dist/types/src/internal/proxy/reactive.d.ts +39 -0
  294. package/dist/types/src/internal/proxy/reactive.d.ts.map +1 -0
  295. package/dist/types/src/internal/proxy/schema-validator.d.ts +15 -0
  296. package/dist/types/src/internal/proxy/schema-validator.d.ts.map +1 -0
  297. package/dist/types/src/internal/proxy/symbols.d.ts +3 -0
  298. package/dist/types/src/internal/proxy/symbols.d.ts.map +1 -0
  299. package/dist/types/src/internal/proxy/typed-handler.d.ts +14 -11
  300. package/dist/types/src/internal/proxy/typed-handler.d.ts.map +1 -1
  301. package/dist/types/src/internal/ref/ref-array.d.ts +4 -4
  302. package/dist/types/src/internal/ref/ref-array.d.ts.map +1 -1
  303. package/dist/types/src/internal/ref/ref.d.ts +14 -6
  304. package/dist/types/src/internal/ref/ref.d.ts.map +1 -1
  305. package/dist/types/src/internal/schema/compose.d.ts.map +1 -1
  306. package/dist/types/src/internal/schema/echo-schema.d.ts +15 -3
  307. package/dist/types/src/internal/schema/echo-schema.d.ts.map +1 -1
  308. package/dist/types/src/internal/schema/index.d.ts +0 -2
  309. package/dist/types/src/internal/schema/index.d.ts.map +1 -1
  310. package/dist/types/src/internal/schema/persistent-schema.d.ts +9 -7
  311. package/dist/types/src/internal/schema/persistent-schema.d.ts.map +1 -1
  312. package/dist/types/src/internal/types/base.d.ts +5 -16
  313. package/dist/types/src/internal/types/base.d.ts.map +1 -1
  314. package/dist/types/src/internal/types/entity.d.ts +27 -2
  315. package/dist/types/src/internal/types/entity.d.ts.map +1 -1
  316. package/dist/types/src/internal/types/meta.d.ts +1 -9
  317. package/dist/types/src/internal/types/meta.d.ts.map +1 -1
  318. package/dist/types/src/testing/test-schema.d.ts +141 -175
  319. package/dist/types/src/testing/test-schema.d.ts.map +1 -1
  320. package/dist/types/src/testing/util.d.ts +6 -1
  321. package/dist/types/src/testing/util.d.ts.map +1 -1
  322. package/dist/types/tsconfig.tsbuildinfo +1 -1
  323. package/package.json +130 -23
  324. package/src/Annotation.ts +5 -4
  325. package/src/Database.ts +229 -82
  326. package/src/Entity.test.ts +22 -0
  327. package/src/Entity.ts +173 -7
  328. package/src/{errors.ts → Err.ts} +2 -2
  329. package/src/Filter.ts +376 -0
  330. package/src/Format.ts +0 -2
  331. package/src/Hypergraph.ts +74 -0
  332. package/src/Obj.test.ts +386 -0
  333. package/src/Obj.ts +338 -250
  334. package/src/{query/order.ts → Order.ts} +19 -9
  335. package/src/{query/query.test.ts → Query.test.ts} +180 -49
  336. package/src/{query/query.ts → Query.ts} +115 -122
  337. package/src/QueryResult.ts +106 -0
  338. package/src/Ref.ts +20 -3
  339. package/src/Relation.test.ts +82 -0
  340. package/src/Relation.ts +364 -27
  341. package/src/SchemaRegistry.ts +105 -0
  342. package/src/Tag.ts +1 -1
  343. package/src/Type.test.ts +52 -0
  344. package/src/Type.ts +322 -88
  345. package/src/index.ts +9 -5
  346. package/src/internal/README.md +36 -17
  347. package/src/internal/annotations/annotations.test.ts +6 -6
  348. package/src/internal/annotations/annotations.ts +73 -76
  349. package/src/internal/annotations/util.ts +2 -0
  350. package/src/internal/api/annotations.ts +60 -0
  351. package/src/internal/api/entity.ts +29 -0
  352. package/src/internal/api/index.ts +19 -0
  353. package/src/internal/api/meta.ts +88 -0
  354. package/src/internal/api/sorting.ts +53 -0
  355. package/src/internal/api/version.ts +96 -0
  356. package/src/internal/entities/entity.ts +36 -19
  357. package/src/internal/entities/index.ts +1 -1
  358. package/src/internal/entities/model.ts +17 -12
  359. package/src/internal/entities/object.ts +20 -5
  360. package/src/internal/entities/relation.ts +22 -4
  361. package/src/internal/formats/format.ts +7 -8
  362. package/src/internal/formats/object.ts +2 -2
  363. package/src/internal/formats/select.ts +5 -3
  364. package/src/internal/formats/string.ts +5 -0
  365. package/src/internal/formats/types.ts +9 -3
  366. package/src/internal/index.ts +2 -1
  367. package/src/internal/json-schema/json-schema-type.ts +1 -1
  368. package/src/internal/json-schema/json-schema.test.ts +19 -17
  369. package/src/internal/json-schema/json-schema.ts +4 -4
  370. package/src/internal/object/clone.ts +48 -0
  371. package/src/internal/object/create-object.ts +2 -2
  372. package/src/internal/object/index.ts +3 -0
  373. package/src/internal/object/inspect.ts +3 -3
  374. package/src/internal/object/json-serializer.test.ts +4 -1
  375. package/src/internal/object/json-serializer.ts +28 -70
  376. package/src/internal/object/schema-validator.ts +2 -238
  377. package/src/internal/object/set-value.test.ts +281 -0
  378. package/src/internal/object/set-value.ts +165 -0
  379. package/src/internal/object/snapshot.ts +70 -0
  380. package/src/internal/object/typed-object.test.ts +11 -11
  381. package/src/internal/object/typed-object.ts +8 -72
  382. package/src/internal/proxy/change-context.ts +138 -0
  383. package/src/internal/proxy/change.test.ts +519 -0
  384. package/src/internal/proxy/define-hidden-property.ts +14 -0
  385. package/src/internal/proxy/errors.ts +42 -0
  386. package/src/internal/proxy/event-batch.ts +44 -0
  387. package/src/internal/proxy/handler.test.ts +30 -80
  388. package/src/internal/proxy/index.ts +11 -0
  389. package/src/internal/proxy/json-serializer.ts +87 -0
  390. package/src/internal/proxy/make-object.ts +33 -50
  391. package/src/internal/proxy/ownership.ts +253 -0
  392. package/src/internal/proxy/proxy-types.ts +23 -0
  393. package/src/internal/proxy/proxy-utils.ts +150 -0
  394. package/src/internal/proxy/reactive-array.ts +71 -0
  395. package/src/internal/proxy/reactive.ts +69 -0
  396. package/src/internal/proxy/schema-validator.ts +244 -0
  397. package/src/internal/proxy/schema.test.ts +23 -15
  398. package/src/internal/proxy/symbols.ts +7 -0
  399. package/src/internal/proxy/typed-handler.test.ts +251 -35
  400. package/src/internal/proxy/typed-handler.ts +265 -56
  401. package/src/internal/proxy/typed-object.test.ts +26 -15
  402. package/src/internal/ref/ref-array.ts +4 -4
  403. package/src/internal/ref/ref.ts +62 -39
  404. package/src/internal/schema/compose.test.ts +3 -3
  405. package/src/internal/schema/compose.ts +1 -2
  406. package/src/internal/schema/echo-schema.ts +49 -11
  407. package/src/internal/schema/index.ts +0 -2
  408. package/src/internal/schema/persistent-schema.ts +3 -4
  409. package/src/internal/types/base.ts +6 -21
  410. package/src/internal/types/entity.ts +35 -4
  411. package/src/internal/types/meta.ts +1 -11
  412. package/src/testing/api.test.ts +31 -5
  413. package/src/testing/test-schema.ts +55 -30
  414. package/src/testing/util.ts +22 -15
  415. package/dist/lib/browser/chunk-7GH6RXJ3.mjs.map +0 -7
  416. package/dist/lib/browser/chunk-E4UTVJNF.mjs +0 -1111
  417. package/dist/lib/browser/chunk-E4UTVJNF.mjs.map +0 -7
  418. package/dist/lib/node-esm/chunk-JE5RXM2I.mjs +0 -1111
  419. package/dist/lib/node-esm/chunk-JE5RXM2I.mjs.map +0 -7
  420. package/dist/lib/node-esm/chunk-M4B6BMD2.mjs.map +0 -7
  421. package/dist/types/src/errors.d.ts.map +0 -1
  422. package/dist/types/src/internal/entities/expando.d.ts +0 -16
  423. package/dist/types/src/internal/entities/expando.d.ts.map +0 -1
  424. package/dist/types/src/internal/schema/runtime-schema-registry.d.ts +0 -18
  425. package/dist/types/src/internal/schema/runtime-schema-registry.d.ts.map +0 -1
  426. package/dist/types/src/internal/schema/snapshot.d.ts +0 -6
  427. package/dist/types/src/internal/schema/snapshot.d.ts.map +0 -1
  428. package/dist/types/src/query/filter.d.ts +0 -167
  429. package/dist/types/src/query/filter.d.ts.map +0 -1
  430. package/dist/types/src/query/index.d.ts +0 -5
  431. package/dist/types/src/query/index.d.ts.map +0 -1
  432. package/dist/types/src/query/order.d.ts +0 -12
  433. package/dist/types/src/query/order.d.ts.map +0 -1
  434. package/dist/types/src/query/query.d.ts.map +0 -1
  435. package/dist/types/src/query/query.test.d.ts +0 -2
  436. package/dist/types/src/query/query.test.d.ts.map +0 -1
  437. package/dist/types/src/query/testing.d.ts +0 -51
  438. package/dist/types/src/query/testing.d.ts.map +0 -1
  439. package/dist/types/src/query/types.d.ts +0 -17
  440. package/dist/types/src/query/types.d.ts.map +0 -1
  441. package/dist/types/src/query/util.d.ts +0 -8
  442. package/dist/types/src/query/util.d.ts.map +0 -1
  443. package/src/internal/entities/expando.ts +0 -23
  444. package/src/internal/schema/runtime-schema-registry.ts +0 -78
  445. package/src/internal/schema/snapshot.ts +0 -25
  446. package/src/query/filter.ts +0 -455
  447. package/src/query/index.ts +0 -9
  448. package/src/query/testing.ts +0 -64
  449. package/src/query/types.ts +0 -23
  450. package/src/query/util.ts +0 -25
@@ -0,0 +1,244 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import * as Schema from 'effect/Schema';
6
+ import * as SchemaAST from 'effect/SchemaAST';
7
+
8
+ import { invariant } from '@dxos/invariant';
9
+ import { log } from '@dxos/log';
10
+
11
+ import { SchemaId } from '../types';
12
+
13
+ // TODO(burdon): Reconcile with @dxos/effect visit().
14
+
15
+ export class SchemaValidator {
16
+ /**
17
+ * Recursively check that schema specifies constructions we can handle.
18
+ * Validates there are no ambiguous discriminated union types.
19
+ */
20
+ public static validateSchema(schema: Schema.Schema.AnyNoContext): void {
21
+ const visitAll = (nodes: SchemaAST.AST[]) => nodes.forEach((node) => this.validateSchema(Schema.make(node)));
22
+ if (SchemaAST.isUnion(schema.ast)) {
23
+ const typeAstList = schema.ast.types.filter((type) => SchemaAST.isTypeLiteral(type)) as SchemaAST.TypeLiteral[];
24
+ // Check we can handle a discriminated union.
25
+ if (typeAstList.length > 1) {
26
+ getTypeDiscriminators(typeAstList);
27
+ }
28
+ visitAll(typeAstList);
29
+ } else if (SchemaAST.isTupleType(schema.ast)) {
30
+ const positionalTypes = schema.ast.elements.map((t) => t.type);
31
+ const allTypes = positionalTypes.concat(schema.ast.rest.map((t) => t.type));
32
+ visitAll(allTypes);
33
+ } else if (SchemaAST.isTypeLiteral(schema.ast)) {
34
+ visitAll(SchemaAST.getPropertySignatures(schema.ast).map((p) => p.type));
35
+ }
36
+ }
37
+
38
+ public static hasTypeAnnotation(
39
+ rootObjectSchema: Schema.Schema.AnyNoContext,
40
+ property: string,
41
+ annotation: symbol,
42
+ ): boolean {
43
+ try {
44
+ let type = this.getPropertySchema(rootObjectSchema, [property]);
45
+ if (SchemaAST.isTupleType(type.ast)) {
46
+ type = this.getPropertySchema(rootObjectSchema, [property, '0']);
47
+ }
48
+
49
+ return type.ast.annotations[annotation] != null;
50
+ } catch {
51
+ return false;
52
+ }
53
+ }
54
+
55
+ public static getPropertySchema(
56
+ rootObjectSchema: Schema.Schema.AnyNoContext,
57
+ propertyPath: KeyPath,
58
+ getProperty: (path: KeyPath) => any = () => null,
59
+ ): Schema.Schema.AnyNoContext {
60
+ let schema: Schema.Schema.AnyNoContext = rootObjectSchema;
61
+ for (let i = 0; i < propertyPath.length; i++) {
62
+ const propertyName = propertyPath[i];
63
+ const tupleAst = unwrapArray(schema.ast);
64
+ if (tupleAst != null) {
65
+ schema = getArrayElementSchema(tupleAst, propertyName);
66
+ } else {
67
+ const propertyType = getPropertyType(schema.ast, propertyName.toString(), (propertyName) =>
68
+ getProperty([...propertyPath.slice(0, i), propertyName]),
69
+ );
70
+ if (propertyType == null) {
71
+ log.warn('unknown property', { path: propertyPath, property: propertyName });
72
+ continue;
73
+ }
74
+
75
+ schema = Schema.make(propertyType).annotations(propertyType.annotations);
76
+ }
77
+ }
78
+
79
+ return schema;
80
+ }
81
+
82
+ public static getTargetPropertySchema(target: any, prop: string | symbol): Schema.Schema.AnyNoContext {
83
+ const schema: Schema.Schema.AnyNoContext | undefined = (target as any)[SchemaId];
84
+ invariant(schema, 'target has no schema');
85
+ const arrayAst = unwrapArray(schema.ast);
86
+ if (arrayAst != null) {
87
+ return getArrayElementSchema(arrayAst, prop);
88
+ }
89
+
90
+ const propertyType = getPropertyType(schema.ast, prop.toString(), (prop) => target[prop]);
91
+ if (propertyType == null) {
92
+ return Schema.Any; // TODO(burdon): HACK.
93
+ }
94
+
95
+ invariant(propertyType, `invalid property: ${prop.toString()}`);
96
+ return Schema.make(propertyType);
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Tuple AST is used both for:
102
+ * fixed-length tuples ([string, number]) in which case AST will be { elements: [Schema.String, Schema.Number] }
103
+ * variable-length arrays (Array<string | number>) in which case AST will be { rest: [Schema.Union(Schema.String, Schema.Number)] }
104
+ */
105
+ const getArrayElementSchema = (
106
+ tupleAst: SchemaAST.TupleType,
107
+ property: string | symbol | number,
108
+ ): Schema.Schema.AnyNoContext => {
109
+ const elementIndex = typeof property === 'string' ? parseInt(property, 10) : Number.NaN;
110
+ if (Number.isNaN(elementIndex)) {
111
+ invariant(property === 'length', `invalid array property: ${String(property)}`);
112
+ return Schema.Number;
113
+ }
114
+ if (elementIndex < tupleAst.elements.length) {
115
+ const elementType = tupleAst.elements[elementIndex].type;
116
+ return Schema.make(elementType).annotations(elementType.annotations);
117
+ }
118
+
119
+ const restType = tupleAst.rest;
120
+ return Schema.make(restType[0].type).annotations(restType[0].annotations);
121
+ };
122
+
123
+ const flattenUnion = (typeAst: SchemaAST.AST): SchemaAST.AST[] =>
124
+ SchemaAST.isUnion(typeAst) ? typeAst.types.flatMap(flattenUnion) : [typeAst];
125
+
126
+ const getProperties = (
127
+ typeAst: SchemaAST.AST,
128
+ getTargetPropertyFn: (propertyName: string) => any,
129
+ ): SchemaAST.PropertySignature[] => {
130
+ const astCandidates = flattenUnion(typeAst);
131
+ const typeAstList = astCandidates.filter((type) => SchemaAST.isTypeLiteral(type)) as SchemaAST.TypeLiteral[];
132
+ if (typeAstList.length === 0) {
133
+ return [];
134
+ }
135
+ if (typeAstList.length === 1) {
136
+ return SchemaAST.getPropertySignatures(typeAstList[0]);
137
+ }
138
+
139
+ const typeDiscriminators = getTypeDiscriminators(typeAstList);
140
+ const targetPropertyValue = getTargetPropertyFn(String(typeDiscriminators[0].name));
141
+ const typeIndex = typeDiscriminators.findIndex((p) => targetPropertyValue === (p.type as SchemaAST.Literal).literal);
142
+ invariant(typeIndex !== -1, 'discriminator field not set on target');
143
+ return SchemaAST.getPropertySignatures(typeAstList[typeIndex]);
144
+ };
145
+
146
+ const getPropertyType = (
147
+ ast: SchemaAST.AST,
148
+ propertyName: string,
149
+ getTargetPropertyFn: (propertyName: string) => any,
150
+ ): SchemaAST.AST | null => {
151
+ const anyOrObject = unwrapAst(
152
+ ast,
153
+ (candidate) => SchemaAST.isAnyKeyword(candidate) || SchemaAST.isObjectKeyword(candidate),
154
+ );
155
+ if (anyOrObject != null) {
156
+ return ast;
157
+ }
158
+
159
+ const typeOrDiscriminatedUnion = unwrapAst(ast, (t) => {
160
+ return SchemaAST.isTypeLiteral(t) || (SchemaAST.isUnion(t) && t.types.some((t) => SchemaAST.isTypeLiteral(t)));
161
+ });
162
+ if (typeOrDiscriminatedUnion == null) {
163
+ return null;
164
+ }
165
+
166
+ const targetProperty = getProperties(typeOrDiscriminatedUnion, getTargetPropertyFn).find(
167
+ (p) => p.name === propertyName,
168
+ );
169
+ if (targetProperty != null) {
170
+ return unwrapAst(targetProperty.type);
171
+ }
172
+
173
+ const indexSignatureType = unwrapAst(ast, SchemaAST.isTypeLiteral);
174
+ if (
175
+ indexSignatureType &&
176
+ SchemaAST.isTypeLiteral(indexSignatureType) &&
177
+ indexSignatureType.indexSignatures.length > 0
178
+ ) {
179
+ return unwrapAst(indexSignatureType.indexSignatures[0].type);
180
+ }
181
+
182
+ return null;
183
+ };
184
+
185
+ const getTypeDiscriminators = (typeAstList: SchemaAST.TypeLiteral[]): SchemaAST.PropertySignature[] => {
186
+ const discriminatorPropCandidates = typeAstList
187
+ .flatMap(SchemaAST.getPropertySignatures)
188
+ .filter((p) => SchemaAST.isLiteral(p.type));
189
+ const propertyName = discriminatorPropCandidates[0].name;
190
+ const isValidDiscriminator = discriminatorPropCandidates.every((p) => p.name === propertyName && !p.isOptional);
191
+ const everyTypeHasDiscriminator = discriminatorPropCandidates.length === typeAstList.length;
192
+ const isDiscriminatedUnion = isValidDiscriminator && everyTypeHasDiscriminator;
193
+ invariant(isDiscriminatedUnion, 'type ambiguity: every type in a union must have a single unique-literal field');
194
+ return discriminatorPropCandidates;
195
+ };
196
+
197
+ /**
198
+ * Used to check that rootAst is for a type matching the provided predicate.
199
+ * That's not always straightforward because types of optionality and recursive types.
200
+ * const Task = Schema.Struct({
201
+ * ...,
202
+ * previous?: Schema.optional(Schema.suspend(() => Task)),
203
+ * });
204
+ * Here the AST for `previous` field is going to be Union(Suspend(Type), Undefined).
205
+ * SchemaAST.isTypeLiteral(field) will return false, but unwrapAst(field, (ast) => SchemaAST.isTypeLiteral(ast))
206
+ * will return true.
207
+ */
208
+ const unwrapAst = (rootAst: SchemaAST.AST, predicate?: (ast: SchemaAST.AST) => boolean): SchemaAST.AST | null => {
209
+ let ast: SchemaAST.AST | undefined = rootAst;
210
+ while (ast != null) {
211
+ if (predicate?.(ast)) {
212
+ return ast;
213
+ }
214
+
215
+ if (SchemaAST.isUnion(ast)) {
216
+ const next: any = ast.types.find((t) => (predicate != null && predicate(t)) || SchemaAST.isSuspend(t));
217
+ if (next != null) {
218
+ ast = next;
219
+ continue;
220
+ }
221
+ }
222
+
223
+ if (SchemaAST.isSuspend(ast)) {
224
+ ast = ast.f();
225
+ } else {
226
+ return predicate == null ? ast : null;
227
+ }
228
+ }
229
+
230
+ return null;
231
+ };
232
+
233
+ const unwrapArray = (ast: SchemaAST.AST) => unwrapAst(ast, SchemaAST.isTupleType) as SchemaAST.TupleType | null;
234
+
235
+ export const checkIdNotPresentOnSchema = (schema: Schema.Schema<any, any, any>) => {
236
+ invariant(SchemaAST.isTypeLiteral(schema.ast));
237
+ const idProperty = SchemaAST.getPropertySignatures(schema.ast).find((prop) => prop.name === 'id');
238
+ if (idProperty != null) {
239
+ throw new Error('"id" property name is reserved');
240
+ }
241
+ };
242
+
243
+ // TODO(burdon): Reconcile with JsonPath.
244
+ type KeyPath = readonly (string | number)[];
@@ -8,23 +8,29 @@ import { describe, expect, test } from 'vitest';
8
8
 
9
9
  import { createEchoSchema } from '../../testing';
10
10
  import { PropertyMeta, getPropertyMetaAnnotation, getTypeAnnotation } from '../annotations';
11
- import { TypedObject } from '../object';
11
+ import { EchoObjectSchema } from '../entities';
12
12
 
13
13
  // TODO(dmaretskyi): Comment.
14
- class EmptySchemaType extends TypedObject({
15
- typename: 'example.com/type/Empty',
16
- version: '0.1.0',
17
- })({}) {}
14
+ const EmptySchemaType = Schema.Struct({}).pipe(
15
+ EchoObjectSchema({
16
+ typename: 'example.com/type/Empty',
17
+ version: '0.1.0',
18
+ }),
19
+ );
20
+
21
+ interface EmptySchemaType extends Schema.Schema.Type<typeof EmptySchemaType> {}
18
22
 
19
23
  describe('dynamic schema', () => {
20
24
  test('getProperties filters out id and unwraps optionality', async () => {
21
- class TestSchema extends TypedObject({
22
- typename: 'example.com/type/Test',
23
- version: '0.1.0',
24
- })({
25
+ const TestSchema = Schema.Struct({
25
26
  field1: Schema.String,
26
27
  field2: Schema.Boolean,
27
- }) {}
28
+ }).pipe(
29
+ EchoObjectSchema({
30
+ typename: 'example.com/type/Test',
31
+ version: '0.1.0',
32
+ }),
33
+ );
28
34
 
29
35
  const registered = createEchoSchema(TestSchema);
30
36
  expect(registered.getProperties().map((p) => [p.name, p.type])).to.deep.eq([
@@ -34,12 +40,14 @@ describe('dynamic schema', () => {
34
40
  });
35
41
 
36
42
  test('addColumns', async () => {
37
- class TestSchema extends TypedObject({
38
- typename: 'example.com/type/Test',
39
- version: '0.1.0',
40
- })({
43
+ const TestSchema = Schema.Struct({
41
44
  field1: Schema.String,
42
- }) {}
45
+ }).pipe(
46
+ EchoObjectSchema({
47
+ typename: 'example.com/type/Test',
48
+ version: '0.1.0',
49
+ }),
50
+ );
43
51
 
44
52
  const registered = createEchoSchema(TestSchema);
45
53
  registered.addFields({ field2: Schema.Boolean });
@@ -0,0 +1,7 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ // TODO(dmaretskyi): Rename all symbols that are props to end with *Key.
6
+ export const EventId = Symbol.for('@dxos/live-object/EventId');
7
+ export const ChangeId = Symbol.for('@dxos/live-object/ChangeId');
@@ -6,22 +6,21 @@ import * as Schema from 'effect/Schema';
6
6
  import { describe, expect, test } from 'vitest';
7
7
 
8
8
  import { TestSchema } from '../../testing';
9
- import { isInstanceOf } from '../annotations';
10
- import { TypedObject, createObject } from '../object';
9
+ import { EchoObjectSchema } from '../entities';
10
+ import { setValue } from '../object';
11
11
  import { Ref } from '../ref';
12
- import { foreignKey, getMeta, getSchema } from '../types';
12
+ import { foreignKey, getMeta } from '../types';
13
13
 
14
14
  import { makeObject } from './make-object';
15
+ import { change, subscribe } from './reactive';
15
16
 
16
17
  describe('complex schema validations', () => {
17
- const setValue = (target: any, prop: string, value: any) => {
18
- target[prop] = value;
19
- };
20
-
21
18
  test('any', () => {
22
19
  const schema = Schema.Struct({ field: Schema.Any });
23
20
  const object = makeObject(schema, { field: { nested: { value: 100 } } });
24
- expect(() => setValue(object, 'field', { any: 'value' })).not.to.throw();
21
+ change(object, (o) => {
22
+ expect(() => (o.field = { any: 'value' })).not.to.throw();
23
+ });
25
24
  });
26
25
 
27
26
  test('meta', () => {
@@ -34,12 +33,18 @@ describe('complex schema validations', () => {
34
33
  test('object', () => {
35
34
  const schema = Schema.Struct({ field: Schema.optional(Schema.Object) });
36
35
  const object = makeObject(schema, { field: { nested: { value: 100 } } });
37
- expect(() => setValue(object, 'field', { any: 'value' })).not.to.throw();
36
+ change(object, (o) => {
37
+ expect(() => (o.field = { any: 'value' })).not.to.throw();
38
+ });
38
39
  });
39
40
 
40
41
  test('references', () => {
41
- class Foo extends TypedObject({ typename: 'example.com/type/Foo', version: '0.1.0' })({ field: Schema.String }) {}
42
- class Bar extends TypedObject({ typename: 'example.com/type/Bar', version: '0.1.0' })({ fooRef: Ref(Foo) }) {}
42
+ const Foo = Schema.Struct({ field: Schema.String }).pipe(
43
+ EchoObjectSchema({ typename: 'example.com/type/Foo', version: '0.1.0' }),
44
+ );
45
+ const Bar = Schema.Struct({ fooRef: Ref(Foo) }).pipe(
46
+ EchoObjectSchema({ typename: 'example.com/type/Bar', version: '0.1.0' }),
47
+ );
43
48
  const field = 'hello';
44
49
  expect(() => makeObject(Bar, { fooRef: { id: '1', field } as any })).to.throw();
45
50
  expect(() => makeObject(Bar, { fooRef: undefined as any })).to.throw(); // Unresolved reference.
@@ -50,8 +55,10 @@ describe('complex schema validations', () => {
50
55
  test('index signatures', () => {
51
56
  const schema = Schema.Struct({}, { key: Schema.String, value: Schema.Number });
52
57
  const object = makeObject(schema, { unknownField: 1 });
53
- expect(() => setValue(object, 'field', '42')).to.throw();
54
- expect(() => setValue(object, 'unknown_field', 42)).not.to.throw();
58
+ change(object, (o) => {
59
+ expect(() => setValue(o, ['field'], '42')).to.throw();
60
+ expect(() => setValue(o, ['unknown_field'], 42)).not.to.throw();
61
+ });
55
62
  });
56
63
 
57
64
  test('suspend', () => {
@@ -61,30 +68,16 @@ describe('complex schema validations', () => {
61
68
  });
62
69
 
63
70
  const object = makeObject(schema, { array: [1, 2, null], object: { field: 3 } });
64
- expect(() => setValue(object, 'object', { field: 4 })).not.to.throw();
65
- expect(() => setValue(object.object, 'field', 4)).not.to.throw();
66
- expect(() => setValue(object.array, '0', 4)).not.to.throw();
67
- expect(() => setValue(object.array, '0', '4')).to.throw();
71
+ change(object, (o) => {
72
+ expect(() => (o.object = { field: 4 })).not.to.throw();
73
+ expect(() => setValue(o, ['object', 'field'], 4)).not.to.throw();
74
+ expect(() => setValue(o, ['array', 0], 4)).not.to.throw();
75
+ expect(() => setValue(o, ['array', 0], '4')).to.throw();
76
+ });
68
77
  });
69
78
 
70
- test('nesting static objects with schema in the live object', () => {
71
- const contact1 = createObject(TestSchema.Person, {
72
- name: 'Robert Smith',
73
- email: 'robert@example.com',
74
- } as any);
75
- const contact2 = createObject(TestSchema.Person, {
76
- name: 'Katy Perry',
77
- email: 'katy@example.com',
78
- } as any);
79
-
80
- const network = makeObject({ contacts: [contact1] });
81
- expect(isInstanceOf(TestSchema.Person, network.contacts[0])).to.eq(true);
82
- expect(getSchema(network.contacts[0])).to.eq(TestSchema.Person);
83
-
84
- network.contacts.push(contact2);
85
- expect(isInstanceOf(TestSchema.Person, network.contacts[1])).to.eq(true);
86
- expect(getSchema(network.contacts[1])).to.eq(TestSchema.Person);
87
- });
79
+ // NOTE: Test for nesting typed objects in untyped containers was removed.
80
+ // Untyped reactive objects are no longer supported - use Atoms for untyped reactive state.
88
81
 
89
82
  test('creating an object with data from another object', () => {
90
83
  const contact = makeObject(TestSchema.Person, {
@@ -99,4 +92,227 @@ describe('complex schema validations', () => {
99
92
 
100
93
  expect((object.value as any).name).to.eq('Robert Smith');
101
94
  });
95
+
96
+ test('subscribe', () => {
97
+ const TestSchema = Schema.mutable(Schema.Struct({ field: Schema.String })).pipe(
98
+ EchoObjectSchema({ typename: 'Test', version: '0.1.0' }),
99
+ );
100
+ const object = makeObject(TestSchema, { field: 'value' });
101
+ let called = 0;
102
+ const unsubscribe = subscribe(object as any, () => {
103
+ called++;
104
+ });
105
+
106
+ change(object, (o) => {
107
+ o.field = 'value2';
108
+ });
109
+ expect(called).to.eq(1);
110
+
111
+ unsubscribe();
112
+ change(object, (o) => {
113
+ o.field = 'value3';
114
+ });
115
+ expect(called).to.eq(1);
116
+ });
117
+ });
118
+
119
+ describe('object structure restrictions', () => {
120
+ const NestedSchema = Schema.mutable(
121
+ Schema.Struct({
122
+ data: Schema.optional(Schema.Any),
123
+ nested: Schema.optional(Schema.Any),
124
+ }),
125
+ );
126
+
127
+ test('prevents direct cycles', () => {
128
+ const obj = makeObject(NestedSchema, { data: null });
129
+ change(obj, (o) => {
130
+ expect(() => {
131
+ o.data = obj;
132
+ }).to.throw('Cannot create cycles');
133
+ });
134
+ });
135
+
136
+ test('prevents indirect cycles via nested objects', () => {
137
+ const obj = makeObject(NestedSchema, {
138
+ nested: { value: 1 },
139
+ });
140
+ change(obj, (o) => {
141
+ expect(() => {
142
+ o.nested.parent = obj;
143
+ }).to.throw('Cannot create cycles');
144
+ });
145
+ });
146
+
147
+ test('copy-on-assign for cross-proxy assignment', () => {
148
+ const obj1 = makeObject(NestedSchema, {
149
+ data: { shared: 'original' },
150
+ });
151
+ const obj2 = makeObject(NestedSchema, {});
152
+
153
+ // Assign obj1's nested data to obj2.
154
+ change(obj2, (o) => {
155
+ o.data = obj1.data;
156
+ });
157
+
158
+ // Should be a copy, not the same reference.
159
+ expect(obj2.data).to.deep.eq({ shared: 'original' });
160
+
161
+ // Modifying obj2.data should not affect obj1.data.
162
+ change(obj2, (o) => {
163
+ o.data.shared = 'modified';
164
+ });
165
+ expect(obj1.data.shared).to.eq('original');
166
+ expect(obj2.data.shared).to.eq('modified');
167
+ });
168
+
169
+ test('allows assigning within same typed object', () => {
170
+ const obj = makeObject(NestedSchema, {
171
+ data: { value: 1 },
172
+ nested: null,
173
+ });
174
+
175
+ // Moving data within the same typed object should work without copying.
176
+ change(obj, (o) => {
177
+ o.nested = o.data;
178
+ o.data = null;
179
+ });
180
+
181
+ expect(obj.nested).to.deep.eq({ value: 1 });
182
+ });
183
+
184
+ test('allows assigning plain objects (not owned by any typed object)', () => {
185
+ const obj = makeObject(NestedSchema, {});
186
+ const plainData = { value: 'plain' };
187
+
188
+ change(obj, (o) => {
189
+ o.data = plainData;
190
+ });
191
+ expect(obj.data).to.deep.eq({ value: 'plain' });
192
+
193
+ // Modifying the original plain object should not affect the typed object
194
+ // (since it's been claimed by the typed object).
195
+ plainData.value = 'changed';
196
+ // The value in obj.data depends on when ownership is claimed.
197
+ // After assignment, the typed object owns it.
198
+ });
199
+
200
+ test('deeply nested objects are owned by root ECHO object', () => {
201
+ const obj = makeObject(NestedSchema, {
202
+ data: {
203
+ level1: {
204
+ level2: {
205
+ value: 'deep',
206
+ },
207
+ },
208
+ },
209
+ });
210
+
211
+ // All nested objects should be owned.
212
+ // Assigning any of them to another ECHO object should trigger copy.
213
+ const obj2 = makeObject(NestedSchema, {});
214
+ change(obj2, (o) => {
215
+ o.data = obj.data.level1;
216
+ });
217
+
218
+ // Should be a copy.
219
+ expect(obj2.data).to.deep.eq({ level2: { value: 'deep' } });
220
+
221
+ // Modifying should not affect original.
222
+ change(obj2, (o) => {
223
+ o.data.level2.value = 'modified';
224
+ });
225
+ expect(obj.data.level1.level2.value).to.eq('deep');
226
+ });
227
+
228
+ test('array elements are owned by root ECHO object', () => {
229
+ const ArraySchema = Schema.mutable(
230
+ Schema.Struct({
231
+ items: Schema.mutable(Schema.Array(Schema.Any)),
232
+ }),
233
+ );
234
+
235
+ const obj1 = makeObject(ArraySchema, {
236
+ items: [{ id: 1 }, { id: 2 }, { id: 3 }],
237
+ });
238
+
239
+ const obj2 = makeObject(ArraySchema, { items: [] });
240
+
241
+ // Assign an array element from obj1 to obj2.
242
+ change(obj2, (o) => {
243
+ o.items.push(obj1.items[0]);
244
+ });
245
+
246
+ // Should be a copy.
247
+ expect(obj2.items[0]).to.deep.eq({ id: 1 });
248
+
249
+ // Modifying should not affect original.
250
+ change(obj2, (o) => {
251
+ o.items[0].id = 100;
252
+ });
253
+ expect(obj1.items[0].id).to.eq(1);
254
+ });
255
+
256
+ test('centralized reactivity - direct property mutation triggers event', () => {
257
+ const obj = makeObject(NestedSchema, {
258
+ data: { value: 1 },
259
+ });
260
+
261
+ let notificationCount = 0;
262
+ const unsubscribe = subscribe(obj as any, () => {
263
+ notificationCount++;
264
+ });
265
+
266
+ // Mutate direct property.
267
+ change(obj, (o) => {
268
+ o.data = { value: 2 };
269
+ });
270
+ expect(notificationCount).to.eq(1);
271
+
272
+ unsubscribe();
273
+ });
274
+
275
+ test('centralized reactivity - nested mutation triggers event on root', () => {
276
+ const obj = makeObject(NestedSchema, {
277
+ data: { level1: { value: 1 } },
278
+ });
279
+
280
+ let notificationCount = 0;
281
+ const unsubscribe = subscribe(obj as any, () => {
282
+ notificationCount++;
283
+ });
284
+
285
+ // Mutate deeply nested property - should trigger event on root.
286
+ change(obj, (o) => {
287
+ o.data.level1.value = 2;
288
+ });
289
+ expect(notificationCount).to.eq(1);
290
+
291
+ // Another nested mutation.
292
+ change(obj, (o) => {
293
+ o.data.level1 = { value: 3 };
294
+ });
295
+ expect(notificationCount).to.eq(2);
296
+
297
+ unsubscribe();
298
+ });
299
+
300
+ test('reassigning owned object to same root does not copy', () => {
301
+ const obj = makeObject(NestedSchema, {
302
+ data: { original: true },
303
+ nested: null,
304
+ });
305
+
306
+ // Get reference to the nested data.
307
+ const originalData = obj.data;
308
+
309
+ // Move within same ECHO object.
310
+ change(obj, (o) => {
311
+ o.nested = o.data;
312
+ o.data = null;
313
+ });
314
+
315
+ // Should be the same object (no copy).
316
+ expect(obj.nested).to.eq(originalData);
317
+ });
102
318
  });