@dxos/echo 0.9.1-main.c7dcc2e112 → 0.10.0
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.
- package/dist/lib/neutral/Annotation.mjs +22 -8
- package/dist/lib/neutral/Database.mjs +3 -3
- package/dist/lib/neutral/Entity.mjs +11 -11
- package/dist/lib/neutral/Err.mjs +7 -3
- package/dist/lib/neutral/Feed.mjs +15 -19
- package/dist/lib/neutral/Filter.mjs +13 -11
- package/dist/lib/neutral/Format.mjs +3 -7
- package/dist/lib/neutral/JsonSchema.mjs +7 -7
- package/dist/lib/neutral/Migration.mjs +11 -11
- package/dist/lib/neutral/Obj.mjs +15 -13
- package/dist/lib/neutral/Order.mjs +1 -1
- package/dist/lib/neutral/Query.mjs +17 -17
- package/dist/lib/neutral/QueryResult.mjs +1 -1
- package/dist/lib/neutral/Ref.mjs +6 -6
- package/dist/lib/neutral/Registry.mjs +1 -1
- package/dist/lib/neutral/Relation.mjs +12 -12
- package/dist/lib/neutral/Tag.mjs +15 -15
- package/dist/lib/neutral/Text.mjs +25 -0
- package/dist/lib/neutral/Text.mjs.map +7 -0
- package/dist/lib/neutral/Type.mjs +10 -10
- package/dist/lib/neutral/chunk-2HKGAQM4.mjs +1394 -0
- package/dist/lib/neutral/chunk-2HKGAQM4.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-O6BH7EPN.mjs → chunk-2ZHECXUR.mjs} +5 -4
- package/dist/lib/neutral/chunk-2ZHECXUR.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-AFANXSGV.mjs → chunk-3KTE2Y7Q.mjs} +20 -20
- package/dist/lib/neutral/chunk-3KTE2Y7Q.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-WZ32BF53.mjs → chunk-3TN2VMI4.mjs} +49 -37
- package/dist/lib/neutral/chunk-3TN2VMI4.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-E7IOTOZD.mjs → chunk-42L4HJ3Z.mjs} +11 -15
- package/dist/lib/neutral/chunk-42L4HJ3Z.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-K3S7D5PR.mjs → chunk-4A2NWKRJ.mjs} +5 -5
- package/dist/lib/neutral/chunk-ACFAOTKJ.mjs +1531 -0
- package/dist/lib/neutral/chunk-ACFAOTKJ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-Z3WMRRAZ.mjs → chunk-BEFR7LEA.mjs} +11 -9
- package/dist/lib/neutral/{chunk-Z3WMRRAZ.mjs.map → chunk-BEFR7LEA.mjs.map} +1 -1
- package/dist/lib/neutral/{chunk-6M2Z6WBH.mjs → chunk-BXIKXT7Q.mjs} +2 -6
- package/dist/lib/neutral/{chunk-6M2Z6WBH.mjs.map → chunk-BXIKXT7Q.mjs.map} +1 -1
- package/dist/lib/neutral/{chunk-3JXQUMUI.mjs → chunk-C57XMMBY.mjs} +21 -20
- package/dist/lib/neutral/chunk-C57XMMBY.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-JZ6LFQU5.mjs → chunk-C62JYFAD.mjs} +82 -8
- package/dist/lib/neutral/chunk-C62JYFAD.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-TF5BSLF6.mjs → chunk-FSGX2R62.mjs} +3 -3
- package/dist/lib/neutral/chunk-FSGX2R62.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-6CEISA3V.mjs → chunk-HBXT3GSB.mjs} +29 -15
- package/dist/lib/neutral/chunk-HBXT3GSB.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-WU3GIANS.mjs → chunk-IQR45HAD.mjs} +1 -1
- package/dist/lib/neutral/chunk-IQR45HAD.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-TFEWTY5A.mjs → chunk-KCBW4BR6.mjs} +4 -8
- package/dist/lib/neutral/chunk-KCBW4BR6.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-4TPQZPLY.mjs → chunk-L3E5IXAE.mjs} +198 -30
- package/dist/lib/neutral/chunk-L3E5IXAE.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-EVK6XBXO.mjs → chunk-PRC4FEKJ.mjs} +2 -2
- package/dist/lib/neutral/chunk-PRC4FEKJ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-NOL7O3BL.mjs → chunk-SCT6FFCR.mjs} +9 -4
- package/dist/lib/neutral/chunk-SCT6FFCR.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-BBFJWWAV.mjs → chunk-TOCVVFK2.mjs} +26 -2
- package/dist/lib/neutral/chunk-TOCVVFK2.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-A53NTBHE.mjs → chunk-U53LSQQA.mjs} +3 -3
- package/dist/lib/neutral/{chunk-A53NTBHE.mjs.map → chunk-U53LSQQA.mjs.map} +1 -1
- package/dist/lib/neutral/{chunk-PLDMJJJC.mjs → chunk-UGFFV2FR.mjs} +2 -2
- package/dist/lib/neutral/{chunk-35INCYOE.mjs → chunk-UWLP4RFM.mjs} +1 -1
- package/dist/lib/neutral/chunk-UWLP4RFM.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-SZ5WB6HF.mjs → chunk-UZHCQ6NI.mjs} +13 -11
- package/dist/lib/neutral/{chunk-SZ5WB6HF.mjs.map → chunk-UZHCQ6NI.mjs.map} +3 -3
- package/dist/lib/neutral/{chunk-L3OBWBV2.mjs → chunk-WKIT2YY5.mjs} +2 -2
- package/dist/lib/neutral/{chunk-HGWQR5KH.mjs → chunk-XB6ISRAO.mjs} +27 -15
- package/dist/lib/neutral/chunk-XB6ISRAO.mjs.map +7 -0
- package/dist/lib/neutral/chunk-XXL42WCB.mjs +84 -0
- package/dist/lib/neutral/chunk-XXL42WCB.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-5GAIWRQB.mjs → chunk-XXWK4J53.mjs} +27 -42
- package/dist/lib/neutral/chunk-XXWK4J53.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +30 -26
- package/dist/lib/neutral/internal/index.mjs +91 -69
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/testing/index.mjs +79 -60
- package/dist/lib/neutral/testing/index.mjs.map +3 -3
- package/dist/types/src/Annotation.d.ts +35 -1
- package/dist/types/src/Annotation.d.ts.map +1 -1
- package/dist/types/src/Collection.d.ts +9 -8
- package/dist/types/src/Collection.d.ts.map +1 -1
- package/dist/types/src/Database.d.ts +16 -0
- package/dist/types/src/Database.d.ts.map +1 -1
- package/dist/types/src/Dataset.d.ts +1 -16
- package/dist/types/src/Dataset.d.ts.map +1 -1
- package/dist/types/src/Err.d.ts +67 -0
- package/dist/types/src/Err.d.ts.map +1 -1
- package/dist/types/src/Feed.d.ts +56 -80
- package/dist/types/src/Feed.d.ts.map +1 -1
- package/dist/types/src/Filter.d.ts +9 -1
- package/dist/types/src/Filter.d.ts.map +1 -1
- package/dist/types/src/Hypergraph.d.ts +2 -9
- package/dist/types/src/Hypergraph.d.ts.map +1 -1
- package/dist/types/src/Migration.d.ts +1 -1
- package/dist/types/src/Migration.d.ts.map +1 -1
- package/dist/types/src/Obj.d.ts +31 -6
- package/dist/types/src/Obj.d.ts.map +1 -1
- package/dist/types/src/Order.d.ts +1 -1
- package/dist/types/src/Order.d.ts.map +1 -1
- package/dist/types/src/Query.d.ts +1 -1
- package/dist/types/src/Query.d.ts.map +1 -1
- package/dist/types/src/QueryResult.d.ts +2 -2
- package/dist/types/src/QueryResult.d.ts.map +1 -1
- package/dist/types/src/Ref.d.ts +8 -4
- package/dist/types/src/Ref.d.ts.map +1 -1
- package/dist/types/src/Registry.d.ts +1 -1
- package/dist/types/src/Relation.d.ts.map +1 -1
- package/dist/types/src/Tag.d.ts +11 -13
- package/dist/types/src/Tag.d.ts.map +1 -1
- package/dist/types/src/Text.d.ts +41 -0
- package/dist/types/src/Text.d.ts.map +1 -0
- package/dist/types/src/Text.test.d.ts +2 -0
- package/dist/types/src/Text.test.d.ts.map +1 -0
- package/dist/types/src/Type.d.ts +33 -20
- package/dist/types/src/Type.d.ts.map +1 -1
- package/dist/types/src/View.d.ts +8 -9
- package/dist/types/src/View.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/annotations.d.ts +9 -0
- package/dist/types/src/internal/Annotation/annotations.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/atoms.d.ts +14 -0
- package/dist/types/src/internal/Annotation/atoms.d.ts.map +1 -0
- package/dist/types/src/internal/Annotation/entity-dictionary.d.ts +13 -0
- package/dist/types/src/internal/Annotation/entity-dictionary.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/api.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/guard.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/model.d.ts +1 -1
- package/dist/types/src/internal/Entity/model.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/object.d.ts +5 -1
- package/dist/types/src/internal/Entity/object.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/relation.d.ts +7 -0
- package/dist/types/src/internal/Entity/relation.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/type-uri.d.ts.map +1 -1
- package/dist/types/src/internal/Filter/index.d.ts +2 -0
- package/dist/types/src/internal/Filter/index.d.ts.map +1 -0
- package/dist/types/src/internal/Filter/match.d.ts +22 -0
- package/dist/types/src/internal/Filter/match.d.ts.map +1 -0
- package/dist/types/src/internal/Format/format.d.ts +0 -2
- package/dist/types/src/internal/Format/format.d.ts.map +1 -1
- package/dist/types/src/internal/Format/index.d.ts +2 -2
- package/dist/types/src/internal/Format/index.d.ts.map +1 -1
- package/dist/types/src/internal/Format/string.d.ts +0 -8
- package/dist/types/src/internal/Format/string.d.ts.map +1 -1
- package/dist/types/src/internal/Format/types.d.ts +2 -1
- package/dist/types/src/internal/Format/types.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/atoms.d.ts +7 -3
- package/dist/types/src/internal/Obj/atoms.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/clone.d.ts +2 -1
- package/dist/types/src/internal/Obj/clone.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/create-object.d.ts +3 -4
- package/dist/types/src/internal/Obj/create-object.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/json-serializer.d.ts.map +1 -1
- package/dist/types/src/internal/Query/index.d.ts +1 -0
- package/dist/types/src/internal/Query/index.d.ts.map +1 -1
- package/dist/types/src/internal/Query/query-result-effect.d.ts +9 -0
- package/dist/types/src/internal/Query/query-result-effect.d.ts.map +1 -0
- package/dist/types/src/internal/Ref/atoms.d.ts +1 -2
- package/dist/types/src/internal/Ref/atoms.d.ts.map +1 -1
- package/dist/types/src/internal/Ref/ref.d.ts +13 -6
- package/dist/types/src/internal/Ref/ref.d.ts.map +1 -1
- package/dist/types/src/internal/common/atom-snapshot.d.ts +8 -0
- package/dist/types/src/internal/common/atom-snapshot.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/make-object.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/proxy-types.d.ts +12 -0
- package/dist/types/src/internal/common/proxy/proxy-types.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/proxy-utils.d.ts +25 -0
- package/dist/types/src/internal/common/proxy/proxy-utils.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/schema-validator.d.ts +5 -0
- package/dist/types/src/internal/common/proxy/schema-validator.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/typed-handler.d.ts +17 -0
- package/dist/types/src/internal/common/proxy/typed-handler.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/entity.d.ts +4 -4
- package/dist/types/src/internal/common/types/entity.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/meta.d.ts +2 -4
- package/dist/types/src/internal/common/types/meta.d.ts.map +1 -1
- package/dist/types/src/internal/index.d.ts +1 -0
- package/dist/types/src/internal/index.d.ts.map +1 -1
- package/dist/types/src/testing/test-schema.d.ts +42 -171
- package/dist/types/src/testing/test-schema.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +20 -13
- package/src/Annotation.test.ts +257 -10
- package/src/Annotation.ts +55 -6
- package/src/Collection.ts +10 -12
- package/src/Database.ts +22 -20
- package/src/Err.ts +22 -0
- package/src/Feed.ts +114 -141
- package/src/Filter.test.ts +38 -0
- package/src/Filter.ts +17 -3
- package/src/Hypergraph.ts +2 -11
- package/src/Migration.ts +1 -1
- package/src/Obj.test.ts +92 -12
- package/src/Obj.ts +36 -5
- package/src/Order.ts +3 -3
- package/src/Query.test.ts +2 -2
- package/src/Query.ts +16 -16
- package/src/QueryResult.ts +2 -2
- package/src/Ref.ts +12 -4
- package/src/Registry.ts +1 -1
- package/src/Relation.ts +1 -1
- package/src/Tag.ts +12 -16
- package/src/Text.test.ts +186 -0
- package/src/Text.ts +116 -0
- package/src/Type.test.ts +52 -24
- package/src/Type.ts +69 -31
- package/src/View.ts +22 -30
- package/src/index.ts +1 -1
- package/src/internal/Annotation/annotations.ts +15 -2
- package/src/internal/Annotation/atoms.ts +107 -0
- package/src/internal/Annotation/entity-dictionary.ts +40 -37
- package/src/internal/Entity/api.ts +1 -1
- package/src/internal/Entity/guard.ts +2 -1
- package/src/internal/Entity/model.ts +2 -2
- package/src/internal/Entity/object.ts +14 -1
- package/src/internal/Entity/relation.ts +19 -0
- package/src/internal/Entity/type-uri.ts +3 -1
- package/src/internal/Filter/index.ts +5 -0
- package/src/internal/Filter/match.ts +284 -0
- package/src/internal/Format/format.ts +0 -2
- package/src/internal/Format/index.ts +2 -2
- package/src/internal/Format/string.ts +0 -12
- package/src/internal/Format/types.ts +4 -2
- package/src/internal/JsonSchema/json-schema.test.ts +82 -54
- package/src/internal/Obj/atoms.ts +31 -18
- package/src/internal/Obj/clone.ts +61 -20
- package/src/internal/Obj/create-object.test.ts +3 -3
- package/src/internal/Obj/create-object.ts +3 -4
- package/src/internal/Obj/inspect.ts +1 -1
- package/src/internal/Obj/json-serializer.test.ts +7 -5
- package/src/internal/Obj/json-serializer.ts +1 -1
- package/src/internal/Obj/schema-validator.test.ts +53 -0
- package/src/internal/Obj/set-value.test.ts +29 -19
- package/src/internal/Query/index.ts +1 -0
- package/src/internal/Query/query-result-effect.ts +35 -0
- package/src/internal/Ref/atoms.ts +23 -3
- package/src/internal/Ref/ref.test.ts +8 -8
- package/src/internal/Ref/ref.ts +26 -20
- package/src/internal/common/atom-snapshot.ts +19 -0
- package/src/internal/common/proxy/make-object.ts +1 -1
- package/src/internal/common/proxy/proxy-types.ts +20 -0
- package/src/internal/common/proxy/proxy-utils.ts +37 -1
- package/src/internal/common/proxy/reactive-array.ts +3 -3
- package/src/internal/common/proxy/reactive.test.ts +1 -1
- package/src/internal/common/proxy/schema-validator.ts +181 -8
- package/src/internal/common/proxy/typed-handler.ts +254 -76
- package/src/internal/common/types/entity.ts +15 -7
- package/src/internal/index.ts +1 -0
- package/src/testing/test-schema.ts +75 -90
- package/dist/lib/neutral/chunk-35INCYOE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-3JXQUMUI.mjs.map +0 -7
- package/dist/lib/neutral/chunk-4TPQZPLY.mjs.map +0 -7
- package/dist/lib/neutral/chunk-5GAIWRQB.mjs.map +0 -7
- package/dist/lib/neutral/chunk-6CEISA3V.mjs.map +0 -7
- package/dist/lib/neutral/chunk-AFANXSGV.mjs.map +0 -7
- package/dist/lib/neutral/chunk-BBFJWWAV.mjs.map +0 -7
- package/dist/lib/neutral/chunk-E7IOTOZD.mjs.map +0 -7
- package/dist/lib/neutral/chunk-EVK6XBXO.mjs.map +0 -7
- package/dist/lib/neutral/chunk-HGWQR5KH.mjs.map +0 -7
- package/dist/lib/neutral/chunk-JZ6LFQU5.mjs.map +0 -7
- package/dist/lib/neutral/chunk-NOL7O3BL.mjs.map +0 -7
- package/dist/lib/neutral/chunk-O6BH7EPN.mjs.map +0 -7
- package/dist/lib/neutral/chunk-TF5BSLF6.mjs.map +0 -7
- package/dist/lib/neutral/chunk-TFEWTY5A.mjs.map +0 -7
- package/dist/lib/neutral/chunk-VQYL2OQF.mjs +0 -2353
- package/dist/lib/neutral/chunk-VQYL2OQF.mjs.map +0 -7
- package/dist/lib/neutral/chunk-WU3GIANS.mjs.map +0 -7
- package/dist/lib/neutral/chunk-WZ32BF53.mjs.map +0 -7
- package/dist/lib/neutral/chunk-X3NUUON4.mjs +0 -184
- package/dist/lib/neutral/chunk-X3NUUON4.mjs.map +0 -7
- package/dist/types/src/exemplars.test.d.ts +0 -2
- package/dist/types/src/exemplars.test.d.ts.map +0 -1
- package/dist/types/src/hierarchy.test.d.ts +0 -2
- package/dist/types/src/hierarchy.test.d.ts.map +0 -1
- package/src/exemplars.test.ts +0 -21
- package/src/hierarchy.test.ts +0 -33
- /package/dist/lib/neutral/{chunk-K3S7D5PR.mjs.map → chunk-4A2NWKRJ.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-PLDMJJJC.mjs.map → chunk-UGFFV2FR.mjs.map} +0 -0
- /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 =
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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 =
|
|
150
|
-
|
|
151
|
-
|
|
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 =
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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 =
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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 =
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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
|
|
|
@@ -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
|
-
*
|
|
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
|
-
|
|
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
|
|
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
|
|
package/src/internal/Ref/ref.ts
CHANGED
|
@@ -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
|
-
|
|
626
|
-
|
|
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 {
|
|
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' &&
|
|
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 {
|
|
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
|
-
//
|
|
24
|
-
const isInitialized =
|
|
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
|
-
|
|
39
|
+
skills: { added: [], removed: [] },
|
|
40
40
|
objects: { added: [], removed: [] },
|
|
41
41
|
};
|
|
42
42
|
const unsubscribe = Obj.subscribe(queueShaped, () => {});
|