@dxos/echo 0.9.1-main.c7dcc2e112 → 0.9.1-staging.ee54ba693a

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 (278) hide show
  1. package/dist/lib/neutral/Annotation.mjs +22 -8
  2. package/dist/lib/neutral/Database.mjs +3 -3
  3. package/dist/lib/neutral/Entity.mjs +11 -11
  4. package/dist/lib/neutral/Err.mjs +7 -3
  5. package/dist/lib/neutral/Feed.mjs +15 -19
  6. package/dist/lib/neutral/Filter.mjs +13 -11
  7. package/dist/lib/neutral/Format.mjs +3 -7
  8. package/dist/lib/neutral/JsonSchema.mjs +7 -7
  9. package/dist/lib/neutral/Migration.mjs +11 -11
  10. package/dist/lib/neutral/Obj.mjs +15 -13
  11. package/dist/lib/neutral/Order.mjs +1 -1
  12. package/dist/lib/neutral/Query.mjs +17 -17
  13. package/dist/lib/neutral/QueryResult.mjs +1 -1
  14. package/dist/lib/neutral/Ref.mjs +6 -6
  15. package/dist/lib/neutral/Registry.mjs +1 -1
  16. package/dist/lib/neutral/Relation.mjs +12 -12
  17. package/dist/lib/neutral/Tag.mjs +15 -15
  18. package/dist/lib/neutral/Text.mjs +25 -0
  19. package/dist/lib/neutral/Text.mjs.map +7 -0
  20. package/dist/lib/neutral/Type.mjs +10 -10
  21. package/dist/lib/neutral/chunk-2HKGAQM4.mjs +1394 -0
  22. package/dist/lib/neutral/chunk-2HKGAQM4.mjs.map +7 -0
  23. package/dist/lib/neutral/{chunk-O6BH7EPN.mjs → chunk-2ZHECXUR.mjs} +5 -4
  24. package/dist/lib/neutral/chunk-2ZHECXUR.mjs.map +7 -0
  25. package/dist/lib/neutral/{chunk-AFANXSGV.mjs → chunk-3KTE2Y7Q.mjs} +20 -20
  26. package/dist/lib/neutral/chunk-3KTE2Y7Q.mjs.map +7 -0
  27. package/dist/lib/neutral/{chunk-WZ32BF53.mjs → chunk-3TN2VMI4.mjs} +49 -37
  28. package/dist/lib/neutral/chunk-3TN2VMI4.mjs.map +7 -0
  29. package/dist/lib/neutral/{chunk-E7IOTOZD.mjs → chunk-42L4HJ3Z.mjs} +11 -15
  30. package/dist/lib/neutral/chunk-42L4HJ3Z.mjs.map +7 -0
  31. package/dist/lib/neutral/{chunk-K3S7D5PR.mjs → chunk-4A2NWKRJ.mjs} +5 -5
  32. package/dist/lib/neutral/chunk-ACFAOTKJ.mjs +1531 -0
  33. package/dist/lib/neutral/chunk-ACFAOTKJ.mjs.map +7 -0
  34. package/dist/lib/neutral/{chunk-Z3WMRRAZ.mjs → chunk-BEFR7LEA.mjs} +11 -9
  35. package/dist/lib/neutral/{chunk-Z3WMRRAZ.mjs.map → chunk-BEFR7LEA.mjs.map} +1 -1
  36. package/dist/lib/neutral/{chunk-6M2Z6WBH.mjs → chunk-BXIKXT7Q.mjs} +2 -6
  37. package/dist/lib/neutral/{chunk-6M2Z6WBH.mjs.map → chunk-BXIKXT7Q.mjs.map} +1 -1
  38. package/dist/lib/neutral/{chunk-3JXQUMUI.mjs → chunk-C57XMMBY.mjs} +21 -20
  39. package/dist/lib/neutral/chunk-C57XMMBY.mjs.map +7 -0
  40. package/dist/lib/neutral/{chunk-JZ6LFQU5.mjs → chunk-C62JYFAD.mjs} +82 -8
  41. package/dist/lib/neutral/chunk-C62JYFAD.mjs.map +7 -0
  42. package/dist/lib/neutral/{chunk-TF5BSLF6.mjs → chunk-FSGX2R62.mjs} +3 -3
  43. package/dist/lib/neutral/chunk-FSGX2R62.mjs.map +7 -0
  44. package/dist/lib/neutral/{chunk-6CEISA3V.mjs → chunk-HBXT3GSB.mjs} +29 -15
  45. package/dist/lib/neutral/chunk-HBXT3GSB.mjs.map +7 -0
  46. package/dist/lib/neutral/{chunk-WU3GIANS.mjs → chunk-IQR45HAD.mjs} +1 -1
  47. package/dist/lib/neutral/chunk-IQR45HAD.mjs.map +7 -0
  48. package/dist/lib/neutral/{chunk-TFEWTY5A.mjs → chunk-KCBW4BR6.mjs} +4 -8
  49. package/dist/lib/neutral/chunk-KCBW4BR6.mjs.map +7 -0
  50. package/dist/lib/neutral/{chunk-4TPQZPLY.mjs → chunk-L3E5IXAE.mjs} +198 -30
  51. package/dist/lib/neutral/chunk-L3E5IXAE.mjs.map +7 -0
  52. package/dist/lib/neutral/{chunk-EVK6XBXO.mjs → chunk-PRC4FEKJ.mjs} +2 -2
  53. package/dist/lib/neutral/chunk-PRC4FEKJ.mjs.map +7 -0
  54. package/dist/lib/neutral/{chunk-NOL7O3BL.mjs → chunk-SCT6FFCR.mjs} +9 -4
  55. package/dist/lib/neutral/chunk-SCT6FFCR.mjs.map +7 -0
  56. package/dist/lib/neutral/{chunk-BBFJWWAV.mjs → chunk-TOCVVFK2.mjs} +26 -2
  57. package/dist/lib/neutral/chunk-TOCVVFK2.mjs.map +7 -0
  58. package/dist/lib/neutral/{chunk-A53NTBHE.mjs → chunk-U53LSQQA.mjs} +3 -3
  59. package/dist/lib/neutral/{chunk-A53NTBHE.mjs.map → chunk-U53LSQQA.mjs.map} +1 -1
  60. package/dist/lib/neutral/{chunk-PLDMJJJC.mjs → chunk-UGFFV2FR.mjs} +2 -2
  61. package/dist/lib/neutral/{chunk-35INCYOE.mjs → chunk-UWLP4RFM.mjs} +1 -1
  62. package/dist/lib/neutral/chunk-UWLP4RFM.mjs.map +7 -0
  63. package/dist/lib/neutral/{chunk-SZ5WB6HF.mjs → chunk-UZHCQ6NI.mjs} +13 -11
  64. package/dist/lib/neutral/{chunk-SZ5WB6HF.mjs.map → chunk-UZHCQ6NI.mjs.map} +3 -3
  65. package/dist/lib/neutral/{chunk-L3OBWBV2.mjs → chunk-WKIT2YY5.mjs} +2 -2
  66. package/dist/lib/neutral/{chunk-HGWQR5KH.mjs → chunk-XB6ISRAO.mjs} +27 -15
  67. package/dist/lib/neutral/chunk-XB6ISRAO.mjs.map +7 -0
  68. package/dist/lib/neutral/chunk-XXL42WCB.mjs +84 -0
  69. package/dist/lib/neutral/chunk-XXL42WCB.mjs.map +7 -0
  70. package/dist/lib/neutral/{chunk-5GAIWRQB.mjs → chunk-XXWK4J53.mjs} +27 -42
  71. package/dist/lib/neutral/chunk-XXWK4J53.mjs.map +7 -0
  72. package/dist/lib/neutral/index.mjs +30 -26
  73. package/dist/lib/neutral/internal/index.mjs +91 -69
  74. package/dist/lib/neutral/meta.json +1 -1
  75. package/dist/lib/neutral/testing/index.mjs +79 -60
  76. package/dist/lib/neutral/testing/index.mjs.map +3 -3
  77. package/dist/types/src/Annotation.d.ts +35 -1
  78. package/dist/types/src/Annotation.d.ts.map +1 -1
  79. package/dist/types/src/Collection.d.ts +9 -8
  80. package/dist/types/src/Collection.d.ts.map +1 -1
  81. package/dist/types/src/Database.d.ts +16 -0
  82. package/dist/types/src/Database.d.ts.map +1 -1
  83. package/dist/types/src/Dataset.d.ts +1 -16
  84. package/dist/types/src/Dataset.d.ts.map +1 -1
  85. package/dist/types/src/Err.d.ts +67 -0
  86. package/dist/types/src/Err.d.ts.map +1 -1
  87. package/dist/types/src/Feed.d.ts +56 -80
  88. package/dist/types/src/Feed.d.ts.map +1 -1
  89. package/dist/types/src/Filter.d.ts +9 -1
  90. package/dist/types/src/Filter.d.ts.map +1 -1
  91. package/dist/types/src/Hypergraph.d.ts +2 -9
  92. package/dist/types/src/Hypergraph.d.ts.map +1 -1
  93. package/dist/types/src/Migration.d.ts +1 -1
  94. package/dist/types/src/Migration.d.ts.map +1 -1
  95. package/dist/types/src/Obj.d.ts +31 -6
  96. package/dist/types/src/Obj.d.ts.map +1 -1
  97. package/dist/types/src/Order.d.ts +1 -1
  98. package/dist/types/src/Order.d.ts.map +1 -1
  99. package/dist/types/src/Query.d.ts +1 -1
  100. package/dist/types/src/Query.d.ts.map +1 -1
  101. package/dist/types/src/QueryResult.d.ts +2 -2
  102. package/dist/types/src/QueryResult.d.ts.map +1 -1
  103. package/dist/types/src/Ref.d.ts +8 -4
  104. package/dist/types/src/Ref.d.ts.map +1 -1
  105. package/dist/types/src/Registry.d.ts +1 -1
  106. package/dist/types/src/Relation.d.ts.map +1 -1
  107. package/dist/types/src/Tag.d.ts +11 -13
  108. package/dist/types/src/Tag.d.ts.map +1 -1
  109. package/dist/types/src/Text.d.ts +41 -0
  110. package/dist/types/src/Text.d.ts.map +1 -0
  111. package/dist/types/src/Text.test.d.ts +2 -0
  112. package/dist/types/src/Text.test.d.ts.map +1 -0
  113. package/dist/types/src/Type.d.ts +33 -20
  114. package/dist/types/src/Type.d.ts.map +1 -1
  115. package/dist/types/src/View.d.ts +8 -9
  116. package/dist/types/src/View.d.ts.map +1 -1
  117. package/dist/types/src/index.d.ts +1 -0
  118. package/dist/types/src/index.d.ts.map +1 -1
  119. package/dist/types/src/internal/Annotation/annotations.d.ts +9 -0
  120. package/dist/types/src/internal/Annotation/annotations.d.ts.map +1 -1
  121. package/dist/types/src/internal/Annotation/atoms.d.ts +14 -0
  122. package/dist/types/src/internal/Annotation/atoms.d.ts.map +1 -0
  123. package/dist/types/src/internal/Annotation/entity-dictionary.d.ts +13 -0
  124. package/dist/types/src/internal/Annotation/entity-dictionary.d.ts.map +1 -1
  125. package/dist/types/src/internal/Entity/api.d.ts.map +1 -1
  126. package/dist/types/src/internal/Entity/guard.d.ts.map +1 -1
  127. package/dist/types/src/internal/Entity/model.d.ts +1 -1
  128. package/dist/types/src/internal/Entity/model.d.ts.map +1 -1
  129. package/dist/types/src/internal/Entity/object.d.ts +5 -1
  130. package/dist/types/src/internal/Entity/object.d.ts.map +1 -1
  131. package/dist/types/src/internal/Entity/relation.d.ts +7 -0
  132. package/dist/types/src/internal/Entity/relation.d.ts.map +1 -1
  133. package/dist/types/src/internal/Entity/type-uri.d.ts.map +1 -1
  134. package/dist/types/src/internal/Filter/index.d.ts +2 -0
  135. package/dist/types/src/internal/Filter/index.d.ts.map +1 -0
  136. package/dist/types/src/internal/Filter/match.d.ts +22 -0
  137. package/dist/types/src/internal/Filter/match.d.ts.map +1 -0
  138. package/dist/types/src/internal/Format/format.d.ts +0 -2
  139. package/dist/types/src/internal/Format/format.d.ts.map +1 -1
  140. package/dist/types/src/internal/Format/index.d.ts +2 -2
  141. package/dist/types/src/internal/Format/index.d.ts.map +1 -1
  142. package/dist/types/src/internal/Format/string.d.ts +0 -8
  143. package/dist/types/src/internal/Format/string.d.ts.map +1 -1
  144. package/dist/types/src/internal/Format/types.d.ts +2 -1
  145. package/dist/types/src/internal/Format/types.d.ts.map +1 -1
  146. package/dist/types/src/internal/Obj/atoms.d.ts +7 -3
  147. package/dist/types/src/internal/Obj/atoms.d.ts.map +1 -1
  148. package/dist/types/src/internal/Obj/clone.d.ts +2 -1
  149. package/dist/types/src/internal/Obj/clone.d.ts.map +1 -1
  150. package/dist/types/src/internal/Obj/create-object.d.ts +3 -4
  151. package/dist/types/src/internal/Obj/create-object.d.ts.map +1 -1
  152. package/dist/types/src/internal/Obj/json-serializer.d.ts.map +1 -1
  153. package/dist/types/src/internal/Query/index.d.ts +1 -0
  154. package/dist/types/src/internal/Query/index.d.ts.map +1 -1
  155. package/dist/types/src/internal/Query/query-result-effect.d.ts +9 -0
  156. package/dist/types/src/internal/Query/query-result-effect.d.ts.map +1 -0
  157. package/dist/types/src/internal/Ref/atoms.d.ts +1 -2
  158. package/dist/types/src/internal/Ref/atoms.d.ts.map +1 -1
  159. package/dist/types/src/internal/Ref/ref.d.ts +13 -6
  160. package/dist/types/src/internal/Ref/ref.d.ts.map +1 -1
  161. package/dist/types/src/internal/common/atom-snapshot.d.ts +8 -0
  162. package/dist/types/src/internal/common/atom-snapshot.d.ts.map +1 -0
  163. package/dist/types/src/internal/common/proxy/make-object.d.ts.map +1 -1
  164. package/dist/types/src/internal/common/proxy/proxy-types.d.ts +12 -0
  165. package/dist/types/src/internal/common/proxy/proxy-types.d.ts.map +1 -1
  166. package/dist/types/src/internal/common/proxy/proxy-utils.d.ts +25 -0
  167. package/dist/types/src/internal/common/proxy/proxy-utils.d.ts.map +1 -1
  168. package/dist/types/src/internal/common/proxy/schema-validator.d.ts +5 -0
  169. package/dist/types/src/internal/common/proxy/schema-validator.d.ts.map +1 -1
  170. package/dist/types/src/internal/common/proxy/typed-handler.d.ts +17 -0
  171. package/dist/types/src/internal/common/proxy/typed-handler.d.ts.map +1 -1
  172. package/dist/types/src/internal/common/types/entity.d.ts +4 -4
  173. package/dist/types/src/internal/common/types/entity.d.ts.map +1 -1
  174. package/dist/types/src/internal/common/types/meta.d.ts +2 -4
  175. package/dist/types/src/internal/common/types/meta.d.ts.map +1 -1
  176. package/dist/types/src/internal/index.d.ts +1 -0
  177. package/dist/types/src/internal/index.d.ts.map +1 -1
  178. package/dist/types/src/testing/test-schema.d.ts +42 -171
  179. package/dist/types/src/testing/test-schema.d.ts.map +1 -1
  180. package/dist/types/tsconfig.tsbuildinfo +1 -1
  181. package/package.json +20 -13
  182. package/src/Annotation.test.ts +257 -10
  183. package/src/Annotation.ts +55 -6
  184. package/src/Collection.ts +10 -12
  185. package/src/Database.ts +22 -20
  186. package/src/Err.ts +22 -0
  187. package/src/Feed.ts +114 -141
  188. package/src/Filter.test.ts +38 -0
  189. package/src/Filter.ts +17 -3
  190. package/src/Hypergraph.ts +2 -11
  191. package/src/Migration.ts +1 -1
  192. package/src/Obj.test.ts +92 -12
  193. package/src/Obj.ts +36 -5
  194. package/src/Order.ts +3 -3
  195. package/src/Query.test.ts +2 -2
  196. package/src/Query.ts +16 -16
  197. package/src/QueryResult.ts +2 -2
  198. package/src/Ref.ts +12 -4
  199. package/src/Registry.ts +1 -1
  200. package/src/Relation.ts +1 -1
  201. package/src/Tag.ts +12 -16
  202. package/src/Text.test.ts +186 -0
  203. package/src/Text.ts +116 -0
  204. package/src/Type.test.ts +52 -24
  205. package/src/Type.ts +69 -31
  206. package/src/View.ts +22 -30
  207. package/src/index.ts +1 -1
  208. package/src/internal/Annotation/annotations.ts +15 -2
  209. package/src/internal/Annotation/atoms.ts +107 -0
  210. package/src/internal/Annotation/entity-dictionary.ts +40 -37
  211. package/src/internal/Entity/api.ts +1 -1
  212. package/src/internal/Entity/guard.ts +2 -1
  213. package/src/internal/Entity/model.ts +2 -2
  214. package/src/internal/Entity/object.ts +14 -1
  215. package/src/internal/Entity/relation.ts +19 -0
  216. package/src/internal/Entity/type-uri.ts +3 -1
  217. package/src/internal/Filter/index.ts +5 -0
  218. package/src/internal/Filter/match.ts +284 -0
  219. package/src/internal/Format/format.ts +0 -2
  220. package/src/internal/Format/index.ts +2 -2
  221. package/src/internal/Format/string.ts +0 -12
  222. package/src/internal/Format/types.ts +4 -2
  223. package/src/internal/JsonSchema/json-schema.test.ts +82 -54
  224. package/src/internal/Obj/atoms.ts +31 -18
  225. package/src/internal/Obj/clone.ts +61 -20
  226. package/src/internal/Obj/create-object.test.ts +3 -3
  227. package/src/internal/Obj/create-object.ts +3 -4
  228. package/src/internal/Obj/inspect.ts +1 -1
  229. package/src/internal/Obj/json-serializer.test.ts +7 -5
  230. package/src/internal/Obj/json-serializer.ts +1 -1
  231. package/src/internal/Obj/schema-validator.test.ts +53 -0
  232. package/src/internal/Obj/set-value.test.ts +29 -19
  233. package/src/internal/Query/index.ts +1 -0
  234. package/src/internal/Query/query-result-effect.ts +35 -0
  235. package/src/internal/Ref/atoms.ts +23 -3
  236. package/src/internal/Ref/ref.test.ts +8 -8
  237. package/src/internal/Ref/ref.ts +26 -20
  238. package/src/internal/common/atom-snapshot.ts +19 -0
  239. package/src/internal/common/proxy/make-object.ts +1 -1
  240. package/src/internal/common/proxy/proxy-types.ts +20 -0
  241. package/src/internal/common/proxy/proxy-utils.ts +37 -1
  242. package/src/internal/common/proxy/reactive-array.ts +3 -3
  243. package/src/internal/common/proxy/reactive.test.ts +1 -1
  244. package/src/internal/common/proxy/schema-validator.ts +181 -8
  245. package/src/internal/common/proxy/typed-handler.ts +254 -76
  246. package/src/internal/common/types/entity.ts +15 -7
  247. package/src/internal/index.ts +1 -0
  248. package/src/testing/test-schema.ts +75 -90
  249. package/dist/lib/neutral/chunk-35INCYOE.mjs.map +0 -7
  250. package/dist/lib/neutral/chunk-3JXQUMUI.mjs.map +0 -7
  251. package/dist/lib/neutral/chunk-4TPQZPLY.mjs.map +0 -7
  252. package/dist/lib/neutral/chunk-5GAIWRQB.mjs.map +0 -7
  253. package/dist/lib/neutral/chunk-6CEISA3V.mjs.map +0 -7
  254. package/dist/lib/neutral/chunk-AFANXSGV.mjs.map +0 -7
  255. package/dist/lib/neutral/chunk-BBFJWWAV.mjs.map +0 -7
  256. package/dist/lib/neutral/chunk-E7IOTOZD.mjs.map +0 -7
  257. package/dist/lib/neutral/chunk-EVK6XBXO.mjs.map +0 -7
  258. package/dist/lib/neutral/chunk-HGWQR5KH.mjs.map +0 -7
  259. package/dist/lib/neutral/chunk-JZ6LFQU5.mjs.map +0 -7
  260. package/dist/lib/neutral/chunk-NOL7O3BL.mjs.map +0 -7
  261. package/dist/lib/neutral/chunk-O6BH7EPN.mjs.map +0 -7
  262. package/dist/lib/neutral/chunk-TF5BSLF6.mjs.map +0 -7
  263. package/dist/lib/neutral/chunk-TFEWTY5A.mjs.map +0 -7
  264. package/dist/lib/neutral/chunk-VQYL2OQF.mjs +0 -2353
  265. package/dist/lib/neutral/chunk-VQYL2OQF.mjs.map +0 -7
  266. package/dist/lib/neutral/chunk-WU3GIANS.mjs.map +0 -7
  267. package/dist/lib/neutral/chunk-WZ32BF53.mjs.map +0 -7
  268. package/dist/lib/neutral/chunk-X3NUUON4.mjs +0 -184
  269. package/dist/lib/neutral/chunk-X3NUUON4.mjs.map +0 -7
  270. package/dist/types/src/exemplars.test.d.ts +0 -2
  271. package/dist/types/src/exemplars.test.d.ts.map +0 -1
  272. package/dist/types/src/hierarchy.test.d.ts +0 -2
  273. package/dist/types/src/hierarchy.test.d.ts.map +0 -1
  274. package/src/exemplars.test.ts +0 -21
  275. package/src/hierarchy.test.ts +0 -33
  276. /package/dist/lib/neutral/{chunk-K3S7D5PR.mjs.map → chunk-4A2NWKRJ.mjs.map} +0 -0
  277. /package/dist/lib/neutral/{chunk-PLDMJJJC.mjs.map → chunk-UGFFV2FR.mjs.map} +0 -0
  278. /package/dist/lib/neutral/{chunk-L3OBWBV2.mjs.map → chunk-WKIT2YY5.mjs.map} +0 -0
@@ -59,10 +59,12 @@ describe('Obj.setValue', () => {
59
59
  value: Schema.optional(Schema.Number),
60
60
  });
61
61
 
62
- const Container = Schema.Struct({
63
- name: Schema.String,
64
- items: Schema.optional(Schema.Array(Item)),
65
- }).pipe(Type.makeObject(DXN.make('com.test.type.container', '0.1.0')));
62
+ const Container = Type.makeObject(DXN.make('com.test.type.container', '0.1.0'))(
63
+ Schema.Struct({
64
+ name: Schema.String,
65
+ items: Schema.optional(Schema.Array(Item)),
66
+ }),
67
+ );
66
68
 
67
69
  const container = Obj.make(Container, { name: 'box' });
68
70
 
@@ -146,9 +148,11 @@ describe('Obj.setValue', () => {
146
148
  });
147
149
 
148
150
  test('handles two-dimensional arrays', ({ expect }) => {
149
- const Matrix = Schema.Struct({
150
- values: Schema.optional(Schema.Array(Schema.Array(Schema.Number))),
151
- }).pipe(Type.makeObject(DXN.make('com.test.type.matrix', '0.1.0')));
151
+ const Matrix = Type.makeObject(DXN.make('com.test.type.matrix', '0.1.0'))(
152
+ Schema.Struct({
153
+ values: Schema.optional(Schema.Array(Schema.Array(Schema.Number))),
154
+ }),
155
+ );
152
156
 
153
157
  const matrix = Obj.make(Matrix, {});
154
158
 
@@ -194,10 +198,12 @@ describe('Obj.setValue', () => {
194
198
  value: Schema.optional(Schema.Number),
195
199
  });
196
200
 
197
- const Container = Schema.Struct({
198
- name: Schema.String,
199
- items: Schema.optional(Schema.Array(Item)),
200
- }).pipe(Type.makeObject(DXN.make('com.test.type.container', '0.1.0')));
201
+ const Container = Type.makeObject(DXN.make('com.test.type.container', '0.1.0'))(
202
+ Schema.Struct({
203
+ name: Schema.String,
204
+ items: Schema.optional(Schema.Array(Item)),
205
+ }),
206
+ );
201
207
 
202
208
  const container = Obj.make(Container, { name: 'box' });
203
209
 
@@ -216,10 +222,12 @@ describe('Obj.setValue', () => {
216
222
  completed: Schema.optional(Schema.Boolean),
217
223
  });
218
224
 
219
- const TodoList = Schema.Struct({
220
- name: Schema.String,
221
- tasks: Schema.optional(Schema.Array(Task)),
222
- }).pipe(Type.makeObject(DXN.make('com.test.type.todoList', '0.1.0')));
225
+ const TodoList = Type.makeObject(DXN.make('com.test.type.todoList', '0.1.0'))(
226
+ Schema.Struct({
227
+ name: Schema.String,
228
+ tasks: Schema.optional(Schema.Array(Task)),
229
+ }),
230
+ );
223
231
 
224
232
  const todoList = Obj.make(TodoList, { name: 'My Tasks' });
225
233
 
@@ -240,10 +248,12 @@ describe('Obj.setValue', () => {
240
248
  label: Schema.optional(Schema.String), // Optional - should not be initialized
241
249
  });
242
250
 
243
- const Container = Schema.Struct({
244
- name: Schema.String,
245
- items: Schema.optional(Schema.Array(Item)),
246
- }).pipe(Type.makeObject(DXN.make('com.test.type.container', '0.1.0')));
251
+ const Container = Type.makeObject(DXN.make('com.test.type.container', '0.1.0'))(
252
+ Schema.Struct({
253
+ name: Schema.String,
254
+ items: Schema.optional(Schema.Array(Item)),
255
+ }),
256
+ );
247
257
 
248
258
  const container = Obj.make(Container, { name: 'box' });
249
259
 
@@ -3,3 +3,4 @@
3
3
  //
4
4
 
5
5
  export * from './pretty';
6
+ export * from './query-result-effect';
@@ -0,0 +1,35 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import * as Effectable from 'effect/Effectable';
7
+ import * as Option from 'effect/Option';
8
+
9
+ import { EffectEx } from '@dxos/effect';
10
+
11
+ import type * as QueryResult from '../../QueryResult';
12
+
13
+ /**
14
+ * Wraps an effect that produces a {@link QueryResult.QueryResult} into a
15
+ * {@link QueryResult.QueryResultEffect}, exposing `.run` and `.first` shorthands that execute the
16
+ * query once. Shared by `Database.query` and `Feed.query` so both surfaces chain identically.
17
+ */
18
+ export const makeQueryResultEffect = <T, E, R>(
19
+ eff: Effect.Effect<QueryResult.QueryResult<T>, E, R>,
20
+ ): QueryResult.QueryResultEffect<T, E, R> => {
21
+ return {
22
+ run: Effect.flatMap(eff, (result) => EffectEx.promiseWithCauseCapture(() => result.run())),
23
+ first: Effect.flatMap(eff, (result) =>
24
+ EffectEx.promiseWithCauseCapture(async () => Option.fromNullable(await result.firstOrUndefined())),
25
+ ),
26
+
27
+ // Effect internals: the result is itself an Effect, so it carries the commit prototype.
28
+ ...Effectable.CommitPrototype,
29
+ commit() {
30
+ return eff;
31
+ },
32
+ // Cast required: Effect's commit protocol is supplied at runtime via `CommitPrototype` and
33
+ // cannot be expressed by the object literal's static type.
34
+ } as any;
35
+ };
@@ -4,17 +4,37 @@
4
4
 
5
5
  import * as Atom from '@effect-atom/atom/Atom';
6
6
 
7
+ import { subscribe } from '../common/proxy/reactive';
8
+ import { ObjectDeletedId } from '../common/types/model-symbols';
7
9
  import type { Ref } from './ref';
8
10
  import { loadRefTarget } from './utils';
9
11
 
10
12
  /**
11
13
  * Atom family for ECHO refs.
12
14
  * Uses ref reference as key — same ref returns same atom.
13
- * This atom only updates once when the ref loads it does not subscribe to target object changes.
14
- * Use `Obj.atom(ref)` if you need reactive snapshots of ECHO objects via a ref.
15
+ * Subscribes to target object changes and resolves to undefined when the target is deleted.
15
16
  */
16
17
  export const refSimpleFamily = Atom.family(<T>(ref: Ref<T>): Atom.Atom<T | undefined> => {
17
18
  return Atom.make<T | undefined>((get) => {
18
- return loadRefTarget(ref, get, (target) => target);
19
+ let unsubscribeTarget: (() => void) | undefined;
20
+
21
+ const setupSubscription = (target: T): T | undefined => {
22
+ // Release any previous subscription before re-subscribing (loadRefTarget may call this more than once).
23
+ // T has no ECHO-proxy constraint at this generic level; `subscribe` and ObjectDeletedId
24
+ // both require the internal proxy shape that cannot be expressed statically here.
25
+ unsubscribeTarget?.();
26
+ unsubscribeTarget = subscribe(target as any, () => {
27
+ const deleted = !!(target as any)[ObjectDeletedId];
28
+ get.setSelf(deleted ? undefined : target);
29
+ });
30
+ const deleted = !!(target as any)[ObjectDeletedId];
31
+ return deleted ? undefined : target;
32
+ };
33
+
34
+ get.addFinalizer(() => {
35
+ unsubscribeTarget?.();
36
+ });
37
+
38
+ return loadRefTarget(ref, get, setupSubscription);
19
39
  });
20
40
  });
@@ -5,7 +5,7 @@
5
5
  import * as Schema from 'effect/Schema';
6
6
  import { describe, expect, test } from 'vitest';
7
7
 
8
- import { EID, EntityId, DXN } from '@dxos/keys';
8
+ import { DXN, EID, EntityId } from '@dxos/keys';
9
9
 
10
10
  import * as Type from '../../Type';
11
11
  import { EchoObjectSchema, getObjectEchoUri } from '../Entity';
@@ -45,16 +45,16 @@ describe('Ref', () => {
45
45
 
46
46
  const json = JSON.parse(JSON.stringify(contact));
47
47
  expect(json).toEqual({
48
- id: contact.id,
48
+ 'id': contact.id,
49
49
  '@type': `dxn:${Type.getTypename(Contact)}:${Type.getVersion(Contact)}`,
50
50
  '@meta': {
51
51
  keys: [],
52
52
  },
53
- name: 'John Doe',
54
- tasks: [
53
+ 'name': 'John Doe',
54
+ 'tasks': [
55
55
  {
56
56
  '/': getObjectEchoUri(task)!.toString(),
57
- target: JSON.parse(JSON.stringify(task)),
57
+ 'target': JSON.parse(JSON.stringify(task)),
58
58
  },
59
59
  ],
60
60
  });
@@ -66,13 +66,13 @@ describe('Ref', () => {
66
66
 
67
67
  const json = JSON.parse(JSON.stringify(contact));
68
68
  expect(json).toEqual({
69
- id: contact.id,
69
+ 'id': contact.id,
70
70
  '@type': `dxn:${Type.getTypename(Contact)}:${Type.getVersion(Contact)}`,
71
71
  '@meta': {
72
72
  keys: [],
73
73
  },
74
- name: 'John Doe',
75
- tasks: [{ '/': getObjectEchoUri(task)!.toString() }],
74
+ 'name': 'John Doe',
75
+ 'tasks': [{ '/': getObjectEchoUri(task)!.toString() }],
76
76
  });
77
77
  });
78
78
 
@@ -189,7 +189,14 @@ export interface Ref<T> extends Pipeable.Pipeable {
189
189
  /**
190
190
  * @returns Promise that will resolves with the target object.
191
191
  * Will load the object from disk if it is not present in the working set.
192
+ * Short-circuits immediately when the target is already loaded.
192
193
  * @throws If the object is not available locally.
194
+ *
195
+ * @idiom org.dxos.echo.refLoad
196
+ * applies: Resolving a ref inside an async function or Effect handler — guarantees the object is available before proceeding
197
+ * instead-of: `ref.target` — not guaranteed to be defined in async contexts; use `await ref.load()` (or `yield* Database.load(ref)` in Effect) to ensure the target is present
198
+ * uses: {@link load}
199
+ * related: org.dxos.echo-react.useObjectReactive
193
200
  */
194
201
  load(): Promise<T>;
195
202
 
@@ -484,9 +491,9 @@ export const makeSettledRequest = (
484
491
  });
485
492
 
486
493
  export class RefImpl<T> implements Ref<T> {
494
+ [RefTypeId] = refVariance;
495
+
487
496
  #uri: URI.URI;
488
- #resolver?: RefResolver = undefined;
489
- #resolved = new Event<void>();
490
497
 
491
498
  /**
492
499
  * Target is set when the reference is created from a specific object.
@@ -494,6 +501,9 @@ export class RefImpl<T> implements Ref<T> {
494
501
  */
495
502
  #target: T | undefined = undefined;
496
503
 
504
+ #resolver?: RefResolver = undefined;
505
+ #resolved = new Event<void>();
506
+
497
507
  /**
498
508
  * Callback to issue a reactive notification when object is resolved.
499
509
  */
@@ -513,13 +523,6 @@ export class RefImpl<T> implements Ref<T> {
513
523
  return this.#uri;
514
524
  }
515
525
 
516
- /**
517
- * @inheritdoc
518
- */
519
- get isAvailable(): boolean {
520
- return this.#target !== undefined || this.#resolver !== undefined;
521
- }
522
-
523
526
  /**
524
527
  * @inheritdoc
525
528
  */
@@ -532,6 +535,17 @@ export class RefImpl<T> implements Ref<T> {
532
535
  return this.#resolver.resolveSync(this.#uri, true, this.#resolverCallback) as T | undefined;
533
536
  }
534
537
 
538
+ /**
539
+ * @inheritdoc
540
+ */
541
+ get isAvailable(): boolean {
542
+ return this.#target !== undefined || this.#resolver !== undefined;
543
+ }
544
+
545
+ get atom(): Atom.Atom<T | undefined> {
546
+ return RefAtoms.refSimpleFamily(this);
547
+ }
548
+
535
549
  /**
536
550
  * @inheritdoc
537
551
  */
@@ -605,8 +619,6 @@ export class RefImpl<T> implements Ref<T> {
605
619
  return this.toString();
606
620
  };
607
621
 
608
- [RefTypeId] = refVariance;
609
-
610
622
  /**
611
623
  * Effect Hash trait. Required for MutableHashMap-based caches (e.g., Atom.family)
612
624
  * to deduplicate Ref instances that point to the same object.
@@ -622,13 +634,12 @@ export class RefImpl<T> implements Ref<T> {
622
634
  return that instanceof RefImpl && this.#uri === that.uri;
623
635
  }
624
636
 
625
- get atom(): Atom.Atom<T | undefined> {
626
- return RefAtoms.refSimpleFamily(this);
637
+ pipe() {
638
+ // eslint-disable-next-line prefer-rest-params
639
+ return Pipeable.pipeArguments(this, arguments);
627
640
  }
628
641
 
629
642
  /**
630
- * Internal method to set the resolver.
631
- *
632
643
  * @internal
633
644
  */
634
645
  _setResolver(resolver: RefResolver): void {
@@ -641,11 +652,6 @@ export class RefImpl<T> implements Ref<T> {
641
652
  _getSavedTarget(): T | undefined {
642
653
  return this.#target;
643
654
  }
644
-
645
- pipe() {
646
- // eslint-disable-next-line prefer-rest-params
647
- return Pipeable.pipeArguments(this, arguments);
648
- }
649
655
  }
650
656
 
651
657
  /**
@@ -0,0 +1,19 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ /**
6
+ * Snapshot a value to create a new reference for atom change-detection and React dependency tracking.
7
+ * Objects and arrays are shallow-copied (a fresh reference each read, so an in-place mutation is
8
+ * observed); primitives are returned as-is (so they dedupe via `!==`). Shared by the object-property
9
+ * and annotation atom families.
10
+ */
11
+ export const snapshotForComparison = <V>(value: V): V => {
12
+ if (Array.isArray(value)) {
13
+ return [...value] as V;
14
+ }
15
+ if (value !== null && typeof value === 'object') {
16
+ return { ...value } as V;
17
+ }
18
+ return value;
19
+ };
@@ -13,7 +13,7 @@ import { MetaId } from '../types/model-symbols';
13
13
  import { defineHiddenProperty } from './define-hidden-property';
14
14
  import { attachTypedJsonSerializer } from './json-serializer';
15
15
  import { createProxy, getProxyTarget, isValidProxyTarget } from './proxy-utils';
16
- import { TypeSource, TypedReactiveHandler, prepareTypedTarget, setMetaOwner } from './typed-handler';
16
+ import { TypedReactiveHandler, TypeSource, prepareTypedTarget, setMetaOwner } from './typed-handler';
17
17
 
18
18
  /**
19
19
  *
@@ -15,6 +15,26 @@ export interface ReactiveHandler<T extends object> extends ProxyHandler<T> {
15
15
  * Called when a proxy is created for this target.
16
16
  */
17
17
  init(target: T): void;
18
+
19
+ /**
20
+ * Replace the string CRDT value at `path` with `newText`, applying a minimal diff so cursors and
21
+ * concurrent edits are preserved. Implemented by handlers that back string fields; `Text.update`
22
+ * dispatches here. Must run inside a change context (`Obj.update`).
23
+ */
24
+ textUpdate?(target: T, path: readonly (string | number)[], newText: string): void;
25
+
26
+ /**
27
+ * Splice the string CRDT value at `path` (character indices, mirroring `Array.splice`): remove
28
+ * `deleteCount` characters at `start` and insert `insert`. Returns the removed substring. `Text.splice`
29
+ * dispatches here. Must run inside a change context (`Obj.update`).
30
+ */
31
+ textSplice?(
32
+ target: T,
33
+ path: readonly (string | number)[],
34
+ start: number,
35
+ deleteCount: number,
36
+ insert: string,
37
+ ): string;
18
38
  }
19
39
 
20
40
  /**
@@ -8,11 +8,30 @@ import { type ReactiveHandler } from './proxy-types';
8
8
 
9
9
  export const symbolIsProxy = Symbol.for('@dxos/schema/Proxy');
10
10
 
11
+ /**
12
+ * Marker placed on a reactive-object behaviour prototype (e.g. the typed handler's
13
+ * `TypedObject` prototype). A record target whose prototype chain carries this marker
14
+ * is a reactive data record — equivalent, for the purposes of the "plain object" gates
15
+ * below, to one rooted directly at `Object.prototype`. This lets a handler move its
16
+ * per-object metadata onto an intermediate prototype without those gates mistaking the
17
+ * record for a foreign class instance.
18
+ */
19
+ export const symbolReactivePrototype = Symbol.for('@dxos/echo/ReactivePrototype');
20
+
11
21
  /**
12
22
  * Internal api.
13
23
  */
14
24
  export const isProxy = (value: unknown) => !!(value as any)?.[symbolIsProxy];
15
25
 
26
+ /**
27
+ * True if `value` is a plain data record — either rooted at `Object.prototype` or carrying
28
+ * a reactive behaviour prototype (see {@link symbolReactivePrototype}).
29
+ */
30
+ export const isReactiveRecord = (value: any): boolean => {
31
+ const proto = Object.getPrototypeOf(value);
32
+ return proto === Object.prototype || (proto != null && !!proto[symbolReactivePrototype]);
33
+ };
34
+
16
35
  export const isValidProxyTarget = (value: any): value is object => {
17
36
  if (value == null || value[symbolIsProxy]) {
18
37
  return false;
@@ -21,7 +40,7 @@ export const isValidProxyTarget = (value: any): value is object => {
21
40
  return true;
22
41
  }
23
42
 
24
- return typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype;
43
+ return typeof value === 'object' && isReactiveRecord(value);
25
44
  };
26
45
 
27
46
  /**
@@ -41,6 +60,23 @@ export const getProxyHandler = <T extends object>(proxy: any): ReactiveHandler<T
41
60
  return getProxySlot<T>(proxy).handler;
42
61
  };
43
62
 
63
+ /**
64
+ * Clamp a splice range to `Array.prototype.splice` semantics for a string of the given `length`:
65
+ * a negative `start` counts from the end, a `start` past the end appends, and `deleteCount` is bounded
66
+ * to the remaining characters. Shared by both reactive handlers so the string CRDT API behaves
67
+ * identically across the in-memory and Automerge backends (Automerge's `splice` otherwise throws on
68
+ * out-of-range indices).
69
+ */
70
+ export const normalizeSpliceRange = (
71
+ length: number,
72
+ start: number,
73
+ deleteCount: number,
74
+ ): { start: number; deleteCount: number } => {
75
+ const safeStart = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
76
+ const safeDeleteCount = Math.max(0, Math.min(deleteCount, length - safeStart));
77
+ return { start: safeStart, deleteCount: safeDeleteCount };
78
+ };
79
+
44
80
  /**
45
81
  * Unsafe method to override id for debugging/testing and migration purposes.
46
82
  * @deprecated
@@ -7,7 +7,7 @@ import { createArrayMethodError } from './errors';
7
7
  import { batchEvents } from './event-batch';
8
8
  import { getEchoRoot } from './ownership';
9
9
  import { getProxyTarget, isProxy } from './proxy-utils';
10
- import { ChangeId, EventId } from './symbols';
10
+ import { EventId } from './symbols';
11
11
 
12
12
  /**
13
13
  * Check if array mutation is allowed (inside a change context).
@@ -20,8 +20,8 @@ const checkArrayMutationAllowed = (arr: any, method: string): void => {
20
20
  // Find the root ECHO object.
21
21
  const echoRoot = getEchoRoot(target);
22
22
 
23
- // Check if initialized (has ChangeId marker or EventId).
24
- const isInitialized = (echoRoot as any)[ChangeId] === true || EventId in echoRoot;
23
+ // A root object owns an `EventId` once initialized; before that, mutations are allowed.
24
+ const isInitialized = EventId in echoRoot;
25
25
  if (!isInitialized) {
26
26
  // Array is still being initialized, allow mutations.
27
27
  return;
@@ -36,7 +36,7 @@ describe('Obj.subscribe', () => {
36
36
  test('returns a no-op unsubscribe for non-proxy inputs', () => {
37
37
  const queueShaped: any = {
38
38
  id: '01KQ5NKXJWSKMRPVTVG2GHV8V3',
39
- blueprints: { added: [], removed: [] },
39
+ skills: { added: [], removed: [] },
40
40
  objects: { added: [], removed: [] },
41
41
  };
42
42
  const unsubscribe = Obj.subscribe(queueShaped, () => {});