@dxos/echo 0.8.4-main.ae835ea → 0.8.4-main.bc674ce

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 (532) hide show
  1. package/README.md +1 -2
  2. package/dist/lib/neutral/Annotation.mjs +32 -0
  3. package/dist/lib/neutral/Database.mjs +17 -0
  4. package/dist/lib/neutral/Entity.mjs +51 -0
  5. package/dist/lib/neutral/Err.mjs +10 -0
  6. package/dist/lib/neutral/Filter.mjs +61 -0
  7. package/dist/lib/neutral/Format.mjs +66 -0
  8. package/dist/lib/neutral/JsonSchema.mjs +19 -0
  9. package/dist/lib/neutral/JsonSchema.mjs.map +7 -0
  10. package/dist/lib/neutral/Key.mjs +12 -0
  11. package/dist/lib/neutral/Key.mjs.map +7 -0
  12. package/dist/lib/neutral/Obj.mjs +90 -0
  13. package/dist/lib/neutral/Obj.mjs.map +7 -0
  14. package/dist/lib/neutral/Order.mjs +12 -0
  15. package/dist/lib/neutral/Order.mjs.map +7 -0
  16. package/dist/lib/neutral/Query.mjs +26 -0
  17. package/dist/lib/neutral/Query.mjs.map +7 -0
  18. package/dist/lib/neutral/QueryResult.mjs +2 -0
  19. package/dist/lib/neutral/QueryResult.mjs.map +7 -0
  20. package/dist/lib/neutral/Ref.mjs +22 -0
  21. package/dist/lib/neutral/Ref.mjs.map +7 -0
  22. package/dist/lib/neutral/Relation.mjs +84 -0
  23. package/dist/lib/neutral/Relation.mjs.map +7 -0
  24. package/dist/lib/neutral/SchemaRegistry.mjs +2 -0
  25. package/dist/lib/neutral/SchemaRegistry.mjs.map +7 -0
  26. package/dist/lib/neutral/Tag.mjs +25 -0
  27. package/dist/lib/neutral/Tag.mjs.map +7 -0
  28. package/dist/lib/neutral/Type.mjs +47 -0
  29. package/dist/lib/neutral/Type.mjs.map +7 -0
  30. package/dist/lib/neutral/chunk-2MTHJ5UW.mjs +203 -0
  31. package/dist/lib/neutral/chunk-2MTHJ5UW.mjs.map +7 -0
  32. package/dist/lib/neutral/chunk-3ZEAZF7T.mjs +23 -0
  33. package/dist/lib/neutral/chunk-3ZEAZF7T.mjs.map +7 -0
  34. package/dist/lib/neutral/chunk-4L6DOFXP.mjs +7 -0
  35. package/dist/lib/neutral/chunk-4L6DOFXP.mjs.map +7 -0
  36. package/dist/lib/neutral/chunk-4TT624YA.mjs +73 -0
  37. package/dist/lib/neutral/chunk-4TT624YA.mjs.map +7 -0
  38. package/dist/lib/neutral/chunk-62DWJ6CE.mjs +402 -0
  39. package/dist/lib/neutral/chunk-62DWJ6CE.mjs.map +7 -0
  40. package/dist/lib/neutral/chunk-6QPSGMEF.mjs +97 -0
  41. package/dist/lib/neutral/chunk-6QPSGMEF.mjs.map +7 -0
  42. package/dist/lib/neutral/chunk-ANHVGJI4.mjs +21 -0
  43. package/dist/lib/neutral/chunk-ANHVGJI4.mjs.map +7 -0
  44. package/dist/lib/neutral/chunk-CUDIBUM4.mjs +282 -0
  45. package/dist/lib/neutral/chunk-CUDIBUM4.mjs.map +7 -0
  46. package/dist/lib/neutral/chunk-HMOXCO27.mjs +40 -0
  47. package/dist/lib/neutral/chunk-HMOXCO27.mjs.map +7 -0
  48. package/dist/lib/neutral/chunk-IP2GHXWA.mjs +56 -0
  49. package/dist/lib/neutral/chunk-IP2GHXWA.mjs.map +7 -0
  50. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +10 -0
  51. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +7 -0
  52. package/dist/lib/neutral/chunk-KRHDMXSU.mjs +132 -0
  53. package/dist/lib/neutral/chunk-KRHDMXSU.mjs.map +7 -0
  54. package/dist/lib/neutral/chunk-NWUO5FKZ.mjs +39 -0
  55. package/dist/lib/neutral/chunk-NWUO5FKZ.mjs.map +7 -0
  56. package/dist/lib/neutral/chunk-OMUPQMLR.mjs +7 -0
  57. package/dist/lib/neutral/chunk-OMUPQMLR.mjs.map +7 -0
  58. package/dist/lib/neutral/chunk-ROKO4RKJ.mjs +42 -0
  59. package/dist/lib/neutral/chunk-ROKO4RKJ.mjs.map +7 -0
  60. package/dist/lib/neutral/chunk-RPB6V4BE.mjs +38 -0
  61. package/dist/lib/neutral/chunk-RPB6V4BE.mjs.map +7 -0
  62. package/dist/lib/neutral/chunk-SU2LVM7J.mjs +3846 -0
  63. package/dist/lib/neutral/chunk-SU2LVM7J.mjs.map +7 -0
  64. package/dist/lib/neutral/chunk-VB5HVDCA.mjs +287 -0
  65. package/dist/lib/neutral/chunk-VB5HVDCA.mjs.map +7 -0
  66. package/dist/lib/neutral/chunk-VR4A4WGG.mjs +249 -0
  67. package/dist/lib/neutral/chunk-VR4A4WGG.mjs.map +7 -0
  68. package/dist/lib/neutral/chunk-X2MPMYYN.mjs +13 -0
  69. package/dist/lib/neutral/chunk-X2MPMYYN.mjs.map +7 -0
  70. package/dist/lib/neutral/chunk-XK5OUUBY.mjs +157 -0
  71. package/dist/lib/neutral/chunk-XK5OUUBY.mjs.map +7 -0
  72. package/dist/lib/neutral/chunk-XMIDBDE6.mjs +142 -0
  73. package/dist/lib/neutral/chunk-XMIDBDE6.mjs.map +7 -0
  74. package/dist/lib/neutral/chunk-YQYMWZAD.mjs +67 -0
  75. package/dist/lib/neutral/chunk-YQYMWZAD.mjs.map +7 -0
  76. package/dist/lib/neutral/index.mjs +84 -0
  77. package/dist/lib/neutral/index.mjs.map +7 -0
  78. package/dist/lib/{node-esm → neutral}/internal/index.mjs +245 -125
  79. package/dist/lib/neutral/internal/index.mjs.map +7 -0
  80. package/dist/lib/neutral/meta.json +1 -0
  81. package/dist/lib/neutral/testing/index.mjs +366 -0
  82. package/dist/lib/neutral/testing/index.mjs.map +7 -0
  83. package/dist/types/src/Annotation.d.ts +2 -0
  84. package/dist/types/src/Annotation.d.ts.map +1 -0
  85. package/dist/types/src/Database.d.ts +194 -0
  86. package/dist/types/src/Database.d.ts.map +1 -0
  87. package/dist/types/src/Entity.d.ts +142 -0
  88. package/dist/types/src/Entity.d.ts.map +1 -0
  89. package/dist/types/src/Entity.test.d.ts +2 -0
  90. package/dist/types/src/Entity.test.d.ts.map +1 -0
  91. package/dist/types/src/{errors.d.ts → Err.d.ts} +23 -31
  92. package/dist/types/src/Err.d.ts.map +1 -0
  93. package/dist/types/src/Filter.d.ts +120 -0
  94. package/dist/types/src/Filter.d.ts.map +1 -0
  95. package/dist/types/src/Format.d.ts +4 -0
  96. package/dist/types/src/Format.d.ts.map +1 -0
  97. package/dist/types/src/Hypergraph.d.ts +60 -0
  98. package/dist/types/src/Hypergraph.d.ts.map +1 -0
  99. package/dist/types/src/JsonSchema.d.ts +9 -0
  100. package/dist/types/src/JsonSchema.d.ts.map +1 -0
  101. package/dist/types/src/Key.d.ts +1 -0
  102. package/dist/types/src/Key.d.ts.map +1 -1
  103. package/dist/types/src/Obj.d.ts +302 -99
  104. package/dist/types/src/Obj.d.ts.map +1 -1
  105. package/dist/types/src/Obj.test.d.ts +2 -0
  106. package/dist/types/src/Obj.test.d.ts.map +1 -0
  107. package/dist/types/src/Order.d.ts +16 -0
  108. package/dist/types/src/Order.d.ts.map +1 -0
  109. package/dist/types/src/Query.d.ts +115 -0
  110. package/dist/types/src/Query.d.ts.map +1 -0
  111. package/dist/types/src/Query.test.d.ts +2 -0
  112. package/dist/types/src/Query.test.d.ts.map +1 -0
  113. package/dist/types/src/QueryResult.d.ts +80 -0
  114. package/dist/types/src/QueryResult.d.ts.map +1 -0
  115. package/dist/types/src/Ref.d.ts +13 -11
  116. package/dist/types/src/Ref.d.ts.map +1 -1
  117. package/dist/types/src/Relation.d.ts +242 -22
  118. package/dist/types/src/Relation.d.ts.map +1 -1
  119. package/dist/types/src/Relation.test.d.ts +2 -0
  120. package/dist/types/src/Relation.test.d.ts.map +1 -0
  121. package/dist/types/src/SchemaRegistry.d.ts +84 -0
  122. package/dist/types/src/SchemaRegistry.d.ts.map +1 -0
  123. package/dist/types/src/Tag.d.ts +17 -0
  124. package/dist/types/src/Tag.d.ts.map +1 -0
  125. package/dist/types/src/Type.d.ts +225 -72
  126. package/dist/types/src/Type.d.ts.map +1 -1
  127. package/dist/types/src/Type.test.d.ts +2 -0
  128. package/dist/types/src/Type.test.d.ts.map +1 -0
  129. package/dist/types/src/index.d.ts +15 -5
  130. package/dist/types/src/index.d.ts.map +1 -1
  131. package/dist/types/src/internal/annotations/annotations.d.ts +170 -0
  132. package/dist/types/src/internal/annotations/annotations.d.ts.map +1 -0
  133. package/dist/types/src/internal/annotations/annotations.test.d.ts.map +1 -0
  134. package/dist/types/src/internal/annotations/index.d.ts +3 -0
  135. package/dist/types/src/internal/annotations/index.d.ts.map +1 -0
  136. package/dist/types/src/internal/annotations/util.d.ts +27 -0
  137. package/dist/types/src/internal/annotations/util.d.ts.map +1 -0
  138. package/dist/types/src/internal/api/annotations.d.ts +23 -0
  139. package/dist/types/src/internal/api/annotations.d.ts.map +1 -0
  140. package/dist/types/src/internal/api/entity.d.ts +13 -0
  141. package/dist/types/src/internal/api/entity.d.ts.map +1 -0
  142. package/dist/types/src/internal/api/index.d.ts +15 -0
  143. package/dist/types/src/internal/api/index.d.ts.map +1 -0
  144. package/dist/types/src/internal/api/meta.d.ts +42 -0
  145. package/dist/types/src/internal/api/meta.d.ts.map +1 -0
  146. package/dist/types/src/internal/api/sorting.d.ts +24 -0
  147. package/dist/types/src/internal/api/sorting.d.ts.map +1 -0
  148. package/dist/types/src/internal/api/version.d.ts +42 -0
  149. package/dist/types/src/internal/api/version.d.ts.map +1 -0
  150. package/dist/types/src/internal/entities/entity.d.ts +20 -0
  151. package/dist/types/src/internal/entities/entity.d.ts.map +1 -0
  152. package/dist/types/src/internal/entities/index.d.ts +6 -0
  153. package/dist/types/src/internal/entities/index.d.ts.map +1 -0
  154. package/dist/types/src/internal/entities/model.d.ts +77 -0
  155. package/dist/types/src/internal/entities/model.d.ts.map +1 -0
  156. package/dist/types/src/internal/entities/object.d.ts +18 -0
  157. package/dist/types/src/internal/entities/object.d.ts.map +1 -0
  158. package/dist/types/src/internal/entities/relation.d.ts +62 -0
  159. package/dist/types/src/internal/entities/relation.d.ts.map +1 -0
  160. package/dist/types/src/internal/entities/util.d.ts +2 -0
  161. package/dist/types/src/internal/entities/util.d.ts.map +1 -0
  162. package/dist/types/src/internal/formats/format.d.ts +4 -2
  163. package/dist/types/src/internal/formats/format.d.ts.map +1 -1
  164. package/dist/types/src/internal/formats/select.d.ts +6 -4
  165. package/dist/types/src/internal/formats/select.d.ts.map +1 -1
  166. package/dist/types/src/internal/formats/string.d.ts +4 -0
  167. package/dist/types/src/internal/formats/string.d.ts.map +1 -1
  168. package/dist/types/src/internal/formats/types.d.ts +13 -9
  169. package/dist/types/src/internal/formats/types.d.ts.map +1 -1
  170. package/dist/types/src/internal/index.d.ts +7 -10
  171. package/dist/types/src/internal/index.d.ts.map +1 -1
  172. package/dist/types/src/internal/json-schema/annotations.d.ts.map +1 -0
  173. package/dist/types/src/internal/json-schema/effect-schema.test.d.ts.map +1 -0
  174. package/dist/types/src/internal/json-schema/index.d.ts +2 -0
  175. package/dist/types/src/internal/json-schema/index.d.ts.map +1 -1
  176. package/dist/types/src/internal/json-schema/json-schema-normalize.d.ts.map +1 -1
  177. package/dist/types/src/internal/json-schema/json-schema-type.d.ts +130 -29
  178. package/dist/types/src/internal/json-schema/json-schema-type.d.ts.map +1 -1
  179. package/dist/types/src/internal/{json → json-schema}/json-schema.d.ts +4 -2
  180. package/dist/types/src/internal/json-schema/json-schema.d.ts.map +1 -0
  181. package/dist/types/src/internal/json-schema/json-schema.test.d.ts.map +1 -0
  182. package/dist/types/src/internal/object/clone.d.ts +8 -0
  183. package/dist/types/src/internal/object/clone.d.ts.map +1 -0
  184. package/dist/types/src/internal/object/common.d.ts.map +1 -1
  185. package/dist/types/src/internal/object/{create.d.ts → create-object.d.ts} +10 -11
  186. package/dist/types/src/internal/object/create-object.d.ts.map +1 -0
  187. package/dist/types/src/internal/object/create-object.test.d.ts +2 -0
  188. package/dist/types/src/internal/object/create-object.test.d.ts.map +1 -0
  189. package/dist/types/src/internal/object/deleted.d.ts +2 -2
  190. package/dist/types/src/internal/object/deleted.d.ts.map +1 -1
  191. package/dist/types/src/internal/object/ids.d.ts.map +1 -1
  192. package/dist/types/src/internal/object/index.d.ts +6 -11
  193. package/dist/types/src/internal/object/index.d.ts.map +1 -1
  194. package/dist/types/src/internal/object/json-serializer.d.ts +14 -9
  195. package/dist/types/src/internal/object/json-serializer.d.ts.map +1 -1
  196. package/dist/types/src/internal/object/schema-validator.d.ts +1 -14
  197. package/dist/types/src/internal/object/schema-validator.d.ts.map +1 -1
  198. package/dist/types/src/internal/object/set-value.d.ts +7 -0
  199. package/dist/types/src/internal/object/set-value.d.ts.map +1 -0
  200. package/dist/types/src/internal/object/set-value.test.d.ts +2 -0
  201. package/dist/types/src/internal/object/set-value.test.d.ts.map +1 -0
  202. package/dist/types/src/internal/object/snapshot.d.ts +6 -0
  203. package/dist/types/src/internal/object/snapshot.d.ts.map +1 -0
  204. package/dist/types/src/internal/object/typed-object.d.ts +8 -14
  205. package/dist/types/src/internal/object/typed-object.d.ts.map +1 -1
  206. package/dist/types/src/internal/proxy/change-context.d.ts +55 -0
  207. package/dist/types/src/internal/proxy/change-context.d.ts.map +1 -0
  208. package/dist/types/src/internal/proxy/change.test.d.ts +2 -0
  209. package/dist/types/src/internal/proxy/change.test.d.ts.map +1 -0
  210. package/dist/types/src/internal/proxy/define-hidden-property.d.ts +5 -0
  211. package/dist/types/src/internal/proxy/define-hidden-property.d.ts.map +1 -0
  212. package/dist/types/src/internal/proxy/errors.d.ts +19 -0
  213. package/dist/types/src/internal/proxy/errors.d.ts.map +1 -0
  214. package/dist/types/src/internal/proxy/event-batch.d.ts +10 -0
  215. package/dist/types/src/internal/proxy/event-batch.d.ts.map +1 -0
  216. package/dist/types/src/internal/proxy/index.d.ts +14 -0
  217. package/dist/types/src/internal/proxy/index.d.ts.map +1 -0
  218. package/dist/types/src/internal/proxy/json-serializer.d.ts +6 -0
  219. package/dist/types/src/internal/proxy/json-serializer.d.ts.map +1 -0
  220. package/dist/types/src/internal/proxy/make-object.d.ts +14 -0
  221. package/dist/types/src/internal/proxy/make-object.d.ts.map +1 -0
  222. package/dist/types/src/internal/proxy/ownership.d.ts +57 -0
  223. package/dist/types/src/internal/proxy/ownership.d.ts.map +1 -0
  224. package/dist/types/src/internal/proxy/proxy-types.d.ts +18 -0
  225. package/dist/types/src/internal/proxy/proxy-types.d.ts.map +1 -0
  226. package/dist/types/src/internal/proxy/proxy-utils.d.ts +47 -0
  227. package/dist/types/src/internal/proxy/proxy-utils.d.ts.map +1 -0
  228. package/dist/types/src/internal/proxy/reactive-array.d.ts +8 -0
  229. package/dist/types/src/internal/proxy/reactive-array.d.ts.map +1 -0
  230. package/dist/types/src/internal/proxy/reactive.d.ts +39 -0
  231. package/dist/types/src/internal/proxy/reactive.d.ts.map +1 -0
  232. package/dist/types/src/internal/proxy/schema-validator.d.ts +15 -0
  233. package/dist/types/src/internal/proxy/schema-validator.d.ts.map +1 -0
  234. package/dist/types/src/internal/proxy/symbols.d.ts +3 -0
  235. package/dist/types/src/internal/proxy/symbols.d.ts.map +1 -0
  236. package/dist/types/src/internal/proxy/typed-handler.d.ts +15 -12
  237. package/dist/types/src/internal/proxy/typed-handler.d.ts.map +1 -1
  238. package/dist/types/src/internal/ref/ref-array.d.ts +4 -4
  239. package/dist/types/src/internal/ref/ref-array.d.ts.map +1 -1
  240. package/dist/types/src/internal/ref/ref.d.ts +29 -17
  241. package/dist/types/src/internal/ref/ref.d.ts.map +1 -1
  242. package/dist/types/src/internal/schema/compose.d.ts +7 -0
  243. package/dist/types/src/internal/schema/compose.d.ts.map +1 -0
  244. package/dist/types/src/internal/schema/compose.test.d.ts.map +1 -0
  245. package/dist/types/src/internal/schema/echo-schema.d.ts +24 -12
  246. package/dist/types/src/internal/schema/echo-schema.d.ts.map +1 -1
  247. package/dist/types/src/internal/schema/index.d.ts +1 -4
  248. package/dist/types/src/internal/schema/index.d.ts.map +1 -1
  249. package/dist/types/src/internal/schema/persistent-schema.d.ts +20 -0
  250. package/dist/types/src/internal/schema/persistent-schema.d.ts.map +1 -0
  251. package/dist/types/src/internal/types/base.d.ts +26 -0
  252. package/dist/types/src/internal/types/base.d.ts.map +1 -0
  253. package/dist/types/src/internal/types/entity.d.ts +37 -0
  254. package/dist/types/src/internal/types/entity.d.ts.map +1 -0
  255. package/dist/types/src/internal/types/index.d.ts +5 -2
  256. package/dist/types/src/internal/types/index.d.ts.map +1 -1
  257. package/dist/types/src/internal/{object → types}/meta.d.ts +17 -16
  258. package/dist/types/src/internal/types/meta.d.ts.map +1 -0
  259. package/dist/types/src/internal/types/typename.d.ts +13 -0
  260. package/dist/types/src/internal/types/typename.d.ts.map +1 -0
  261. package/dist/types/src/internal/{object → types}/version.d.ts +3 -2
  262. package/dist/types/src/internal/types/version.d.ts.map +1 -0
  263. package/dist/types/src/{test → testing}/api.test.d.ts.map +1 -1
  264. package/dist/types/src/testing/index.d.ts +3 -3
  265. package/dist/types/src/testing/index.d.ts.map +1 -1
  266. package/dist/types/src/testing/test-data.d.ts +18 -0
  267. package/dist/types/src/testing/test-data.d.ts.map +1 -0
  268. package/dist/types/src/testing/test-schema.d.ts +303 -0
  269. package/dist/types/src/testing/test-schema.d.ts.map +1 -0
  270. package/dist/types/src/testing/util.d.ts +21 -0
  271. package/dist/types/src/testing/util.d.ts.map +1 -0
  272. package/dist/types/tsconfig.tsbuildinfo +1 -1
  273. package/package.json +101 -65
  274. package/src/Annotation.ts +18 -0
  275. package/src/Database.ts +336 -0
  276. package/src/Entity.test.ts +22 -0
  277. package/src/Entity.ts +217 -0
  278. package/src/{errors.ts → Err.ts} +2 -2
  279. package/src/Filter.ts +376 -0
  280. package/src/Format.ts +9 -0
  281. package/src/Hypergraph.ts +74 -0
  282. package/src/JsonSchema.ts +16 -0
  283. package/src/Key.ts +3 -0
  284. package/src/Obj.test.ts +386 -0
  285. package/src/Obj.ts +449 -275
  286. package/src/Order.ts +44 -0
  287. package/src/Query.test.ts +465 -0
  288. package/src/Query.ts +296 -0
  289. package/src/QueryResult.ts +106 -0
  290. package/src/Ref.ts +26 -9
  291. package/src/Relation.test.ts +82 -0
  292. package/src/Relation.ts +411 -60
  293. package/src/SchemaRegistry.ts +105 -0
  294. package/src/{query/tag.ts → Tag.ts} +10 -7
  295. package/src/Type.test.ts +52 -0
  296. package/src/Type.ts +361 -114
  297. package/src/index.ts +16 -6
  298. package/src/internal/README.md +102 -0
  299. package/src/internal/{ast → annotations}/annotations.test.ts +18 -20
  300. package/src/internal/annotations/annotations.ts +460 -0
  301. package/src/internal/annotations/index.ts +6 -0
  302. package/src/internal/annotations/util.ts +72 -0
  303. package/src/internal/api/annotations.ts +60 -0
  304. package/src/internal/api/entity.ts +29 -0
  305. package/src/internal/api/index.ts +19 -0
  306. package/src/internal/api/meta.ts +88 -0
  307. package/src/internal/api/sorting.ts +53 -0
  308. package/src/internal/api/version.ts +96 -0
  309. package/src/internal/entities/entity.ts +126 -0
  310. package/src/internal/entities/index.ts +9 -0
  311. package/src/internal/entities/model.ts +134 -0
  312. package/src/internal/entities/object.ts +58 -0
  313. package/src/internal/entities/relation.ts +171 -0
  314. package/src/internal/entities/util.ts +33 -0
  315. package/src/internal/formats/date.test.ts +1 -1
  316. package/src/internal/formats/date.ts +5 -5
  317. package/src/internal/formats/format.test.ts +6 -6
  318. package/src/internal/formats/format.ts +8 -6
  319. package/src/internal/formats/number.ts +5 -5
  320. package/src/internal/formats/object.ts +4 -4
  321. package/src/internal/formats/select.ts +6 -4
  322. package/src/internal/formats/string.ts +14 -9
  323. package/src/internal/formats/types.ts +53 -42
  324. package/src/internal/index.ts +30 -13
  325. package/src/internal/{json → json-schema}/annotations.ts +1 -1
  326. package/src/internal/json-schema/index.ts +2 -0
  327. package/src/internal/json-schema/json-schema-normalize.ts +4 -2
  328. package/src/internal/json-schema/json-schema-type.ts +35 -35
  329. package/src/internal/{json → json-schema}/json-schema.test.ts +73 -69
  330. package/src/internal/{json → json-schema}/json-schema.ts +27 -14
  331. package/src/internal/object/clone.ts +48 -0
  332. package/src/internal/object/common.ts +3 -4
  333. package/src/internal/object/{create.test.ts → create-object.test.ts} +31 -33
  334. package/src/internal/object/{create.ts → create-object.ts} +36 -37
  335. package/src/internal/object/deleted.ts +6 -6
  336. package/src/internal/object/ids.ts +1 -1
  337. package/src/internal/object/index.ts +6 -11
  338. package/src/internal/object/inspect.ts +5 -7
  339. package/src/internal/object/json-serializer.test.ts +36 -37
  340. package/src/internal/object/json-serializer.ts +65 -102
  341. package/src/internal/object/schema-validator.test.ts +3 -7
  342. package/src/internal/object/schema-validator.ts +2 -237
  343. package/src/internal/object/set-value.test.ts +281 -0
  344. package/src/internal/object/set-value.ts +165 -0
  345. package/src/internal/object/snapshot.ts +70 -0
  346. package/src/internal/object/typed-object.test.ts +11 -11
  347. package/src/internal/object/typed-object.ts +8 -66
  348. package/src/internal/proxy/change-context.ts +138 -0
  349. package/src/internal/proxy/change.test.ts +519 -0
  350. package/src/internal/proxy/define-hidden-property.ts +14 -0
  351. package/src/internal/proxy/errors.ts +42 -0
  352. package/src/internal/proxy/event-batch.ts +44 -0
  353. package/src/internal/proxy/handler.test.ts +51 -91
  354. package/src/internal/proxy/index.ts +17 -0
  355. package/src/internal/proxy/json-serializer.ts +87 -0
  356. package/src/internal/proxy/make-object.ts +96 -0
  357. package/src/internal/proxy/ownership.ts +253 -0
  358. package/src/internal/proxy/proxy-types.ts +23 -0
  359. package/src/internal/proxy/proxy-utils.ts +150 -0
  360. package/src/internal/proxy/reactive-array.ts +71 -0
  361. package/src/internal/proxy/reactive.ts +69 -0
  362. package/src/internal/proxy/schema-validator.ts +244 -0
  363. package/src/internal/proxy/schema.test.ts +27 -18
  364. package/src/internal/proxy/symbols.ts +7 -0
  365. package/src/internal/proxy/typed-handler.test.ts +260 -48
  366. package/src/internal/proxy/typed-handler.ts +275 -61
  367. package/src/internal/proxy/typed-object.test.ts +54 -38
  368. package/src/internal/ref/ref-array.ts +4 -4
  369. package/src/internal/ref/ref.test.ts +10 -9
  370. package/src/internal/ref/ref.ts +83 -55
  371. package/src/internal/{projection → schema}/compose.test.ts +8 -9
  372. package/src/internal/{projection → schema}/compose.ts +13 -8
  373. package/src/internal/schema/echo-schema.ts +73 -33
  374. package/src/internal/schema/index.ts +1 -4
  375. package/src/internal/schema/manipulation.ts +1 -1
  376. package/src/internal/schema/persistent-schema.ts +27 -0
  377. package/src/internal/types/base.ts +43 -0
  378. package/src/internal/types/entity.ts +54 -0
  379. package/src/internal/types/index.ts +5 -2
  380. package/src/internal/types/meta.ts +65 -0
  381. package/src/internal/types/typename.ts +45 -0
  382. package/src/internal/types/version.ts +20 -0
  383. package/src/testing/api.test.ts +126 -0
  384. package/src/testing/index.ts +3 -3
  385. package/src/testing/test-data.ts +130 -0
  386. package/src/testing/test-schema.ts +238 -0
  387. package/src/testing/util.ts +85 -0
  388. package/dist/lib/browser/chunk-JUTFUT73.mjs +0 -175
  389. package/dist/lib/browser/chunk-JUTFUT73.mjs.map +0 -7
  390. package/dist/lib/browser/chunk-KEBVBR65.mjs +0 -3727
  391. package/dist/lib/browser/chunk-KEBVBR65.mjs.map +0 -7
  392. package/dist/lib/browser/chunk-WO76TDT6.mjs +0 -814
  393. package/dist/lib/browser/chunk-WO76TDT6.mjs.map +0 -7
  394. package/dist/lib/browser/index.mjs +0 -35
  395. package/dist/lib/browser/internal/index.mjs +0 -336
  396. package/dist/lib/browser/meta.json +0 -1
  397. package/dist/lib/browser/query/index.mjs +0 -15
  398. package/dist/lib/browser/testing/index.mjs +0 -283
  399. package/dist/lib/browser/testing/index.mjs.map +0 -7
  400. package/dist/lib/node-esm/chunk-DWZYQ2UR.mjs +0 -3727
  401. package/dist/lib/node-esm/chunk-DWZYQ2UR.mjs.map +0 -7
  402. package/dist/lib/node-esm/chunk-KBD3A2I6.mjs +0 -175
  403. package/dist/lib/node-esm/chunk-KBD3A2I6.mjs.map +0 -7
  404. package/dist/lib/node-esm/chunk-ZSSII3JW.mjs +0 -814
  405. package/dist/lib/node-esm/chunk-ZSSII3JW.mjs.map +0 -7
  406. package/dist/lib/node-esm/index.mjs +0 -35
  407. package/dist/lib/node-esm/meta.json +0 -1
  408. package/dist/lib/node-esm/query/index.mjs +0 -15
  409. package/dist/lib/node-esm/testing/index.mjs +0 -283
  410. package/dist/lib/node-esm/testing/index.mjs.map +0 -7
  411. package/dist/types/src/errors.d.ts.map +0 -1
  412. package/dist/types/src/internal/ast/annotation-helper.d.ts +0 -8
  413. package/dist/types/src/internal/ast/annotation-helper.d.ts.map +0 -1
  414. package/dist/types/src/internal/ast/annotations.d.ts +0 -131
  415. package/dist/types/src/internal/ast/annotations.d.ts.map +0 -1
  416. package/dist/types/src/internal/ast/annotations.test.d.ts.map +0 -1
  417. package/dist/types/src/internal/ast/entity-kind.d.ts +0 -10
  418. package/dist/types/src/internal/ast/entity-kind.d.ts.map +0 -1
  419. package/dist/types/src/internal/ast/index.d.ts +0 -5
  420. package/dist/types/src/internal/ast/index.d.ts.map +0 -1
  421. package/dist/types/src/internal/ast/types.d.ts +0 -6
  422. package/dist/types/src/internal/ast/types.d.ts.map +0 -1
  423. package/dist/types/src/internal/json/annotations.d.ts.map +0 -1
  424. package/dist/types/src/internal/json/effect-schema.test.d.ts.map +0 -1
  425. package/dist/types/src/internal/json/index.d.ts +0 -2
  426. package/dist/types/src/internal/json/index.d.ts.map +0 -1
  427. package/dist/types/src/internal/json/json-schema.d.ts.map +0 -1
  428. package/dist/types/src/internal/json/json-schema.test.d.ts.map +0 -1
  429. package/dist/types/src/internal/object/accessors.d.ts +0 -37
  430. package/dist/types/src/internal/object/accessors.d.ts.map +0 -1
  431. package/dist/types/src/internal/object/create.d.ts.map +0 -1
  432. package/dist/types/src/internal/object/create.test.d.ts +0 -2
  433. package/dist/types/src/internal/object/create.test.d.ts.map +0 -1
  434. package/dist/types/src/internal/object/entity.d.ts +0 -33
  435. package/dist/types/src/internal/object/entity.d.ts.map +0 -1
  436. package/dist/types/src/internal/object/expando.d.ts +0 -14
  437. package/dist/types/src/internal/object/expando.d.ts.map +0 -1
  438. package/dist/types/src/internal/object/meta.d.ts.map +0 -1
  439. package/dist/types/src/internal/object/model.d.ts +0 -117
  440. package/dist/types/src/internal/object/model.d.ts.map +0 -1
  441. package/dist/types/src/internal/object/relation.d.ts +0 -17
  442. package/dist/types/src/internal/object/relation.d.ts.map +0 -1
  443. package/dist/types/src/internal/object/typename.d.ts +0 -15
  444. package/dist/types/src/internal/object/typename.d.ts.map +0 -1
  445. package/dist/types/src/internal/object/version.d.ts.map +0 -1
  446. package/dist/types/src/internal/projection/compose.d.ts +0 -6
  447. package/dist/types/src/internal/projection/compose.d.ts.map +0 -1
  448. package/dist/types/src/internal/projection/compose.test.d.ts.map +0 -1
  449. package/dist/types/src/internal/projection/index.d.ts +0 -2
  450. package/dist/types/src/internal/projection/index.d.ts.map +0 -1
  451. package/dist/types/src/internal/proxy/reactive-object.d.ts +0 -15
  452. package/dist/types/src/internal/proxy/reactive-object.d.ts.map +0 -1
  453. package/dist/types/src/internal/query/index.d.ts +0 -2
  454. package/dist/types/src/internal/query/index.d.ts.map +0 -1
  455. package/dist/types/src/internal/query/query.d.ts +0 -17
  456. package/dist/types/src/internal/query/query.d.ts.map +0 -1
  457. package/dist/types/src/internal/schema/runtime-schema-registry.d.ts +0 -18
  458. package/dist/types/src/internal/schema/runtime-schema-registry.d.ts.map +0 -1
  459. package/dist/types/src/internal/schema/snapshot.d.ts +0 -6
  460. package/dist/types/src/internal/schema/snapshot.d.ts.map +0 -1
  461. package/dist/types/src/internal/schema/stored-schema.d.ts +0 -13
  462. package/dist/types/src/internal/schema/stored-schema.d.ts.map +0 -1
  463. package/dist/types/src/internal/testing/index.d.ts +0 -3
  464. package/dist/types/src/internal/testing/index.d.ts.map +0 -1
  465. package/dist/types/src/internal/testing/types.d.ts +0 -455
  466. package/dist/types/src/internal/testing/types.d.ts.map +0 -1
  467. package/dist/types/src/internal/testing/utils.d.ts +0 -10
  468. package/dist/types/src/internal/testing/utils.d.ts.map +0 -1
  469. package/dist/types/src/internal/types/types.d.ts +0 -79
  470. package/dist/types/src/internal/types/types.d.ts.map +0 -1
  471. package/dist/types/src/internal/types/types.test.d.ts +0 -2
  472. package/dist/types/src/internal/types/types.test.d.ts.map +0 -1
  473. package/dist/types/src/internal/types/util.d.ts +0 -5
  474. package/dist/types/src/internal/types/util.d.ts.map +0 -1
  475. package/dist/types/src/query/index.d.ts +0 -3
  476. package/dist/types/src/query/index.d.ts.map +0 -1
  477. package/dist/types/src/query/query.d.ts +0 -248
  478. package/dist/types/src/query/query.d.ts.map +0 -1
  479. package/dist/types/src/query/query.test.d.ts +0 -2
  480. package/dist/types/src/query/query.test.d.ts.map +0 -1
  481. package/dist/types/src/query/tag.d.ts +0 -17
  482. package/dist/types/src/query/tag.d.ts.map +0 -1
  483. package/dist/types/src/testing/echo-schema.d.ts +0 -7
  484. package/dist/types/src/testing/echo-schema.d.ts.map +0 -1
  485. package/dist/types/src/testing/types.d.ts +0 -113
  486. package/dist/types/src/testing/types.d.ts.map +0 -1
  487. package/src/internal/ast/annotation-helper.ts +0 -22
  488. package/src/internal/ast/annotations.ts +0 -226
  489. package/src/internal/ast/entity-kind.ts +0 -15
  490. package/src/internal/ast/index.ts +0 -8
  491. package/src/internal/ast/types.ts +0 -17
  492. package/src/internal/json/index.ts +0 -5
  493. package/src/internal/object/accessors.ts +0 -153
  494. package/src/internal/object/entity.ts +0 -248
  495. package/src/internal/object/expando.ts +0 -21
  496. package/src/internal/object/meta.ts +0 -61
  497. package/src/internal/object/model.ts +0 -170
  498. package/src/internal/object/relation.ts +0 -24
  499. package/src/internal/object/typename.ts +0 -61
  500. package/src/internal/object/version.ts +0 -22
  501. package/src/internal/projection/index.ts +0 -5
  502. package/src/internal/proxy/reactive-object.ts +0 -108
  503. package/src/internal/query/index.ts +0 -5
  504. package/src/internal/query/query.ts +0 -23
  505. package/src/internal/schema/runtime-schema-registry.ts +0 -78
  506. package/src/internal/schema/snapshot.ts +0 -25
  507. package/src/internal/schema/stored-schema.ts +0 -26
  508. package/src/internal/testing/index.ts +0 -6
  509. package/src/internal/testing/types.ts +0 -211
  510. package/src/internal/testing/utils.ts +0 -54
  511. package/src/internal/types/types.test.ts +0 -48
  512. package/src/internal/types/types.ts +0 -176
  513. package/src/internal/types/util.ts +0 -9
  514. package/src/query/index.ts +0 -6
  515. package/src/query/query.test.ts +0 -401
  516. package/src/query/query.ts +0 -789
  517. package/src/test/api.test.ts +0 -180
  518. package/src/testing/echo-schema.ts +0 -39
  519. package/src/testing/types.ts +0 -91
  520. /package/dist/lib/{browser/index.mjs.map → neutral/Annotation.mjs.map} +0 -0
  521. /package/dist/lib/{browser/internal/index.mjs.map → neutral/Database.mjs.map} +0 -0
  522. /package/dist/lib/{browser/query/index.mjs.map → neutral/Entity.mjs.map} +0 -0
  523. /package/dist/lib/{node-esm/index.mjs.map → neutral/Err.mjs.map} +0 -0
  524. /package/dist/lib/{node-esm/internal/index.mjs.map → neutral/Filter.mjs.map} +0 -0
  525. /package/dist/lib/{node-esm/query/index.mjs.map → neutral/Format.mjs.map} +0 -0
  526. /package/dist/types/src/internal/{ast → annotations}/annotations.test.d.ts +0 -0
  527. /package/dist/types/src/internal/{json → json-schema}/annotations.d.ts +0 -0
  528. /package/dist/types/src/internal/{json → json-schema}/effect-schema.test.d.ts +0 -0
  529. /package/dist/types/src/internal/{json → json-schema}/json-schema.test.d.ts +0 -0
  530. /package/dist/types/src/internal/{projection → schema}/compose.test.d.ts +0 -0
  531. /package/dist/types/src/{test → testing}/api.test.d.ts +0 -0
  532. /package/src/internal/{json → json-schema}/effect-schema.test.ts +0 -0
@@ -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)[];
@@ -6,24 +6,31 @@ import * as Schema from 'effect/Schema';
6
6
  import * as SchemaAST from 'effect/SchemaAST';
7
7
  import { describe, expect, test } from 'vitest';
8
8
 
9
- import { PropertyMeta, TypedObject, getPropertyMetaAnnotation, getTypeAnnotation } from '..';
10
- import { createEchoSchema } from '../../testing/echo-schema';
9
+ import { createEchoSchema } from '../../testing';
10
+ import { PropertyMeta, getPropertyMetaAnnotation, getTypeAnnotation } from '../annotations';
11
+ import { EchoObjectSchema } from '../entities';
11
12
 
12
13
  // TODO(dmaretskyi): Comment.
13
- class EmptySchemaType extends TypedObject({
14
- typename: 'example.com/type/Empty',
15
- version: '0.1.0',
16
- })({}) {}
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> {}
17
22
 
18
23
  describe('dynamic schema', () => {
19
24
  test('getProperties filters out id and unwraps optionality', async () => {
20
- class TestSchema extends TypedObject({
21
- typename: 'example.com/type/Test',
22
- version: '0.1.0',
23
- })({
25
+ const TestSchema = Schema.Struct({
24
26
  field1: Schema.String,
25
27
  field2: Schema.Boolean,
26
- }) {}
28
+ }).pipe(
29
+ EchoObjectSchema({
30
+ typename: 'example.com/type/Test',
31
+ version: '0.1.0',
32
+ }),
33
+ );
27
34
 
28
35
  const registered = createEchoSchema(TestSchema);
29
36
  expect(registered.getProperties().map((p) => [p.name, p.type])).to.deep.eq([
@@ -33,12 +40,14 @@ describe('dynamic schema', () => {
33
40
  });
34
41
 
35
42
  test('addColumns', async () => {
36
- class TestSchema extends TypedObject({
37
- typename: 'example.com/type/Test',
38
- version: '0.1.0',
39
- })({
43
+ const TestSchema = Schema.Struct({
40
44
  field1: Schema.String,
41
- }) {}
45
+ }).pipe(
46
+ EchoObjectSchema({
47
+ typename: 'example.com/type/Test',
48
+ version: '0.1.0',
49
+ }),
50
+ );
42
51
 
43
52
  const registered = createEchoSchema(TestSchema);
44
53
  registered.addFields({ field2: Schema.Boolean });
@@ -95,7 +104,7 @@ describe('dynamic schema', () => {
95
104
  test('updates typename', async ({ expect }) => {
96
105
  // Create schema with some fields and annotations.
97
106
  const registered = createEchoSchema(EmptySchemaType);
98
- const originalVersion = registered.storedSchema.version;
107
+ const originalVersion = registered.persistentSchema.version;
99
108
  registered.addFields({
100
109
  name: Schema.String.pipe(PropertyMeta('test', { maxLength: 10 })),
101
110
  age: Schema.Number,
@@ -111,7 +120,7 @@ describe('dynamic schema', () => {
111
120
  expect(registered.jsonSchema.typename).toBe(newTypename1);
112
121
 
113
122
  // Version preservation check.
114
- expect(registered.storedSchema.version).toBe(originalVersion);
123
+ expect(registered.persistentSchema.version).toBe(originalVersion);
115
124
 
116
125
  // Field preservation check.
117
126
  const properties = registered.getProperties();
@@ -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');
@@ -5,50 +5,60 @@
5
5
  import * as Schema from 'effect/Schema';
6
6
  import { describe, expect, test } from 'vitest';
7
7
 
8
- import { Ref, TypedObject, create, foreignKey, getMeta, getSchema, isInstanceOf } from '..';
9
- import { Testing } from '../testing';
8
+ import { TestSchema } from '../../testing';
9
+ import { EchoObjectSchema } from '../entities';
10
+ import { setValue } from '../object';
11
+ import { Ref } from '../ref';
12
+ import { foreignKey, getMeta } from '../types';
10
13
 
11
- import { live } from './reactive-object';
14
+ import { makeObject } from './make-object';
15
+ import { change, subscribe } from './reactive';
12
16
 
13
17
  describe('complex schema validations', () => {
14
- const setValue = (target: any, prop: string, value: any) => {
15
- target[prop] = value;
16
- };
17
-
18
18
  test('any', () => {
19
19
  const schema = Schema.Struct({ field: Schema.Any });
20
- const object = live(schema, { field: { nested: { value: 100 } } });
21
- expect(() => setValue(object, 'field', { any: 'value' })).not.to.throw();
20
+ const object = makeObject(schema, { field: { nested: { value: 100 } } });
21
+ change(object, (o) => {
22
+ expect(() => (o.field = { any: 'value' })).not.to.throw();
23
+ });
22
24
  });
23
25
 
24
26
  test('meta', () => {
25
27
  const source = 'test';
26
28
  const schema = Schema.Struct({ field: Schema.Number });
27
- const object = live(schema, { field: 42 }, { keys: [foreignKey(source, '123')] });
29
+ const object = makeObject(schema, { field: 42 }, { keys: [foreignKey(source, '123')] });
28
30
  expect(getMeta(object).keys).to.deep.eq([foreignKey(source, '123')]);
29
31
  });
30
32
 
31
33
  test('object', () => {
32
34
  const schema = Schema.Struct({ field: Schema.optional(Schema.Object) });
33
- const object = live(schema, { field: { nested: { value: 100 } } });
34
- expect(() => setValue(object, 'field', { any: 'value' })).not.to.throw();
35
+ const object = makeObject(schema, { field: { nested: { value: 100 } } });
36
+ change(object, (o) => {
37
+ expect(() => (o.field = { any: 'value' })).not.to.throw();
38
+ });
35
39
  });
36
40
 
37
41
  test('references', () => {
38
- class Foo extends TypedObject({ typename: 'example.com/type/Foo', version: '0.1.0' })({ field: Schema.String }) {}
39
- 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
+ );
40
48
  const field = 'hello';
41
- expect(() => live(Bar, { fooRef: { id: '1', field } as any })).to.throw();
42
- expect(() => live(Bar, { fooRef: undefined as any })).to.throw(); // Unresolved reference.
43
- const bar = live(Bar, { fooRef: Ref.make(live(Foo, { field })) });
49
+ expect(() => makeObject(Bar, { fooRef: { id: '1', field } as any })).to.throw();
50
+ expect(() => makeObject(Bar, { fooRef: undefined as any })).to.throw(); // Unresolved reference.
51
+ const bar = makeObject(Bar, { fooRef: Ref.make(makeObject(Foo, { field })) });
44
52
  expect(bar.fooRef.target?.field).to.eq(field);
45
53
  });
46
54
 
47
55
  test('index signatures', () => {
48
56
  const schema = Schema.Struct({}, { key: Schema.String, value: Schema.Number });
49
- const object = live(schema, { unknownField: 1 });
50
- expect(() => setValue(object, 'field', '42')).to.throw();
51
- expect(() => setValue(object, 'unknown_field', 42)).not.to.throw();
57
+ const object = makeObject(schema, { unknownField: 1 });
58
+ change(object, (o) => {
59
+ expect(() => setValue(o, ['field'], '42')).to.throw();
60
+ expect(() => setValue(o, ['unknown_field'], 42)).not.to.throw();
61
+ });
52
62
  });
53
63
 
54
64
  test('suspend', () => {
@@ -57,46 +67,248 @@ describe('complex schema validations', () => {
57
67
  object: Schema.optional(Schema.suspend(() => Schema.Union(Schema.Null, Schema.Struct({ field: Schema.Number })))),
58
68
  });
59
69
 
60
- const object = live(schema, { array: [1, 2, null], object: { field: 3 } });
61
- expect(() => setValue(object, 'object', { field: 4 })).not.to.throw();
62
- expect(() => setValue(object.object, 'field', 4)).not.to.throw();
63
- expect(() => setValue(object.array, '0', 4)).not.to.throw();
64
- expect(() => setValue(object.array, '0', '4')).to.throw();
70
+ const object = makeObject(schema, { array: [1, 2, null], object: { field: 3 } });
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
+ });
65
77
  });
66
78
 
67
- test('nesting static objects with schema in the live object', () => {
68
- const contact1 = create(Testing.Contact, {
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.
81
+
82
+ test('creating an object with data from another object', () => {
83
+ const contact = makeObject(TestSchema.Person, {
69
84
  name: 'Robert Smith',
70
85
  email: 'robert@example.com',
71
- } as any);
72
- const contact2 = create(Testing.Contact, {
73
- name: 'Katy Perry',
74
- email: 'katy@example.com',
75
- } as any);
86
+ });
87
+
88
+ const TempSchema = Schema.Struct({ value: Schema.Unknown });
89
+ const object = makeObject(TempSchema, {
90
+ value: contact,
91
+ });
76
92
 
77
- const contactBook = live({
78
- contacts: [contact1],
93
+ expect((object.value as any).name).to.eq('Robert Smith');
94
+ });
95
+
96
+ test('subscribe', () => {
97
+ const TestSchema = 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++;
79
104
  });
80
105
 
81
- expect(isInstanceOf(Testing.Contact, contactBook.contacts[0])).to.eq(true);
82
- expect(getSchema(contactBook.contacts[0])).to.eq(Testing.Contact);
106
+ change(object, (o) => {
107
+ o.field = 'value2';
108
+ });
109
+ expect(called).to.eq(1);
83
110
 
84
- contactBook.contacts.push(contact2);
85
- expect(isInstanceOf(Testing.Contact, contactBook.contacts[1])).to.eq(true);
86
- expect(getSchema(contactBook.contacts[1])).to.eq(Testing.Contact);
111
+ unsubscribe();
112
+ change(object, (o) => {
113
+ o.field = 'value3';
114
+ });
115
+ expect(called).to.eq(1);
87
116
  });
117
+ });
88
118
 
89
- test('creating an object with data from another object', () => {
90
- const contact = live(Testing.Contact, {
91
- name: 'Robert Smith',
92
- email: 'robert@example.com',
119
+ describe('object structure restrictions', () => {
120
+ const NestedSchema = Schema.Struct({
121
+ data: Schema.optional(Schema.Any),
122
+ nested: Schema.optional(Schema.Any),
123
+ });
124
+
125
+ test('prevents direct cycles', () => {
126
+ const obj = makeObject(NestedSchema, { data: null });
127
+ change(obj, (o) => {
128
+ expect(() => {
129
+ o.data = obj;
130
+ }).to.throw('Cannot create cycles');
131
+ });
132
+ });
133
+
134
+ test('prevents indirect cycles via nested objects', () => {
135
+ const obj = makeObject(NestedSchema, {
136
+ nested: { value: 1 },
93
137
  });
94
- const TestSchema = Schema.Struct({
95
- value: Schema.Unknown,
138
+ change(obj, (o) => {
139
+ expect(() => {
140
+ o.nested.parent = obj;
141
+ }).to.throw('Cannot create cycles');
96
142
  });
97
- const data = live(TestSchema, {
98
- value: contact,
143
+ });
144
+
145
+ test('copy-on-assign for cross-proxy assignment', () => {
146
+ const obj1 = makeObject(NestedSchema, {
147
+ data: { shared: 'original' },
148
+ });
149
+ const obj2 = makeObject(NestedSchema, {});
150
+
151
+ // Assign obj1's nested data to obj2.
152
+ change(obj2, (o) => {
153
+ o.data = obj1.data;
154
+ });
155
+
156
+ // Should be a copy, not the same reference.
157
+ expect(obj2.data).to.deep.eq({ shared: 'original' });
158
+
159
+ // Modifying obj2.data should not affect obj1.data.
160
+ change(obj2, (o) => {
161
+ o.data.shared = 'modified';
162
+ });
163
+ expect(obj1.data.shared).to.eq('original');
164
+ expect(obj2.data.shared).to.eq('modified');
165
+ });
166
+
167
+ test('allows assigning within same typed object', () => {
168
+ const obj = makeObject(NestedSchema, {
169
+ data: { value: 1 },
170
+ nested: null,
171
+ });
172
+
173
+ // Moving data within the same typed object should work without copying.
174
+ change(obj, (o) => {
175
+ o.nested = o.data;
176
+ o.data = null;
99
177
  });
100
- expect((data.value as any).name).to.eq('Robert Smith');
178
+
179
+ expect(obj.nested).to.deep.eq({ value: 1 });
180
+ });
181
+
182
+ test('allows assigning plain objects (not owned by any typed object)', () => {
183
+ const obj = makeObject(NestedSchema, {});
184
+ const plainData = { value: 'plain' };
185
+
186
+ change(obj, (o) => {
187
+ o.data = plainData;
188
+ });
189
+ expect(obj.data).to.deep.eq({ value: 'plain' });
190
+
191
+ // Modifying the original plain object should not affect the typed object
192
+ // (since it's been claimed by the typed object).
193
+ plainData.value = 'changed';
194
+ // The value in obj.data depends on when ownership is claimed.
195
+ // After assignment, the typed object owns it.
196
+ });
197
+
198
+ test('deeply nested objects are owned by root ECHO object', () => {
199
+ const obj = makeObject(NestedSchema, {
200
+ data: {
201
+ level1: {
202
+ level2: {
203
+ value: 'deep',
204
+ },
205
+ },
206
+ },
207
+ });
208
+
209
+ // All nested objects should be owned.
210
+ // Assigning any of them to another ECHO object should trigger copy.
211
+ const obj2 = makeObject(NestedSchema, {});
212
+ change(obj2, (o) => {
213
+ o.data = obj.data.level1;
214
+ });
215
+
216
+ // Should be a copy.
217
+ expect(obj2.data).to.deep.eq({ level2: { value: 'deep' } });
218
+
219
+ // Modifying should not affect original.
220
+ change(obj2, (o) => {
221
+ o.data.level2.value = 'modified';
222
+ });
223
+ expect(obj.data.level1.level2.value).to.eq('deep');
224
+ });
225
+
226
+ test('array elements are owned by root ECHO object', () => {
227
+ const ArraySchema = Schema.Struct({
228
+ items: Schema.Array(Schema.Any),
229
+ });
230
+
231
+ const obj1 = makeObject(ArraySchema, {
232
+ items: [{ id: 1 }, { id: 2 }, { id: 3 }],
233
+ });
234
+
235
+ const obj2 = makeObject(ArraySchema, { items: [] });
236
+
237
+ // Assign an array element from obj1 to obj2.
238
+ change(obj2, (o) => {
239
+ o.items.push(obj1.items[0]);
240
+ });
241
+
242
+ // Should be a copy.
243
+ expect(obj2.items[0]).to.deep.eq({ id: 1 });
244
+
245
+ // Modifying should not affect original.
246
+ change(obj2, (o) => {
247
+ o.items[0].id = 100;
248
+ });
249
+ expect(obj1.items[0].id).to.eq(1);
250
+ });
251
+
252
+ test('centralized reactivity - direct property mutation triggers event', () => {
253
+ const obj = makeObject(NestedSchema, {
254
+ data: { value: 1 },
255
+ });
256
+
257
+ let notificationCount = 0;
258
+ const unsubscribe = subscribe(obj as any, () => {
259
+ notificationCount++;
260
+ });
261
+
262
+ // Mutate direct property.
263
+ change(obj, (o) => {
264
+ o.data = { value: 2 };
265
+ });
266
+ expect(notificationCount).to.eq(1);
267
+
268
+ unsubscribe();
269
+ });
270
+
271
+ test('centralized reactivity - nested mutation triggers event on root', () => {
272
+ const obj = makeObject(NestedSchema, {
273
+ data: { level1: { value: 1 } },
274
+ });
275
+
276
+ let notificationCount = 0;
277
+ const unsubscribe = subscribe(obj as any, () => {
278
+ notificationCount++;
279
+ });
280
+
281
+ // Mutate deeply nested property - should trigger event on root.
282
+ change(obj, (o) => {
283
+ o.data.level1.value = 2;
284
+ });
285
+ expect(notificationCount).to.eq(1);
286
+
287
+ // Another nested mutation.
288
+ change(obj, (o) => {
289
+ o.data.level1 = { value: 3 };
290
+ });
291
+ expect(notificationCount).to.eq(2);
292
+
293
+ unsubscribe();
294
+ });
295
+
296
+ test('reassigning owned object to same root does not copy', () => {
297
+ const obj = makeObject(NestedSchema, {
298
+ data: { original: true },
299
+ nested: null,
300
+ });
301
+
302
+ // Get reference to the nested data.
303
+ const originalData = obj.data;
304
+
305
+ // Move within same ECHO object.
306
+ change(obj, (o) => {
307
+ o.nested = o.data;
308
+ o.data = null;
309
+ });
310
+
311
+ // Should be the same object (no copy).
312
+ expect(obj.nested).to.eq(originalData);
101
313
  });
102
314
  });