@dxos/echo 0.8.4-main.40e3dcdf1b → 0.8.4-main.43cb759274
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/LICENSE +102 -5
- package/README.md +7 -7
- package/dist/lib/neutral/Annotation.mjs +29 -6
- package/dist/lib/neutral/Database.mjs +8 -9
- package/dist/lib/neutral/Entity.mjs +29 -18
- package/dist/lib/neutral/Err.mjs +3 -3
- package/dist/lib/neutral/Feed.mjs +27 -19
- package/dist/lib/neutral/Filter.mjs +25 -15
- package/dist/lib/neutral/Format.mjs +23 -3
- package/dist/lib/neutral/JsonSchema.mjs +7 -8
- package/dist/lib/neutral/Key.mjs +9 -5
- package/dist/lib/neutral/Migration.mjs +18 -0
- package/dist/lib/neutral/Obj.mjs +25 -19
- package/dist/lib/neutral/Order.mjs +1 -1
- package/dist/lib/neutral/Query.mjs +19 -16
- package/dist/lib/neutral/QueryResult.mjs +1 -1
- package/dist/lib/neutral/Ref.mjs +10 -9
- package/dist/lib/neutral/Registry.mjs +14 -0
- package/dist/lib/neutral/Registry.mjs.map +7 -0
- package/dist/lib/neutral/Relation.mjs +26 -24
- package/dist/lib/neutral/Scope.mjs +12 -0
- package/dist/lib/neutral/Scope.mjs.map +7 -0
- package/dist/lib/neutral/Tag.mjs +17 -13
- package/dist/lib/neutral/Type.mjs +52 -26
- package/dist/lib/neutral/chunk-3DKP2EIN.mjs +31 -0
- package/dist/lib/neutral/chunk-3DKP2EIN.mjs.map +7 -0
- package/dist/lib/neutral/chunk-4BB4MFCN.mjs +154 -0
- package/dist/lib/neutral/chunk-4BB4MFCN.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-CIRHIEMW.mjs → chunk-4SFPZJVA.mjs} +92 -112
- package/dist/lib/neutral/chunk-4SFPZJVA.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-YWXWXIE5.mjs → chunk-4Z6GET2X.mjs} +3 -3
- package/dist/lib/neutral/chunk-4Z6GET2X.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-ANHVGJI4.mjs → chunk-7LOUAPYZ.mjs} +9 -5
- package/dist/lib/neutral/chunk-7LOUAPYZ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-43Y5DOS6.mjs → chunk-7OAFN3OX.mjs} +75 -112
- package/dist/lib/neutral/chunk-7OAFN3OX.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-BOZZPUXE.mjs → chunk-7PRCIDHH.mjs} +41 -81
- package/dist/lib/neutral/chunk-7PRCIDHH.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-UBEZSGXY.mjs → chunk-BBFJWWAV.mjs} +6 -6
- package/dist/lib/neutral/chunk-BBFJWWAV.mjs.map +7 -0
- package/dist/lib/neutral/chunk-BDQGMDIX.mjs +132 -0
- package/dist/lib/neutral/chunk-BDQGMDIX.mjs.map +7 -0
- package/dist/lib/neutral/chunk-CGTI5MXO.mjs +36 -0
- package/dist/lib/neutral/chunk-CGTI5MXO.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-OMUPQMLR.mjs → chunk-DKLUHO4T.mjs} +1 -1
- package/dist/lib/neutral/chunk-DKLUHO4T.mjs.map +7 -0
- package/dist/lib/neutral/chunk-DMN2CKPX.mjs +93 -0
- package/dist/lib/neutral/chunk-DMN2CKPX.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-UTBRYVQC.mjs → chunk-G6CFWUYH.mjs} +2 -2
- package/dist/lib/neutral/chunk-H26LSXVJ.mjs +653 -0
- package/dist/lib/neutral/chunk-H26LSXVJ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-FXEG7EOK.mjs → chunk-J3MNM65T.mjs} +9 -6
- package/dist/lib/neutral/chunk-J3MNM65T.mjs.map +7 -0
- package/dist/lib/neutral/chunk-JE7AOSWF.mjs +247 -0
- package/dist/lib/neutral/chunk-JE7AOSWF.mjs.map +7 -0
- package/dist/lib/neutral/chunk-LAF3LSWI.mjs +379 -0
- package/dist/lib/neutral/chunk-LAF3LSWI.mjs.map +7 -0
- package/dist/lib/neutral/chunk-LMNRFOVB.mjs +108 -0
- package/dist/lib/neutral/chunk-LMNRFOVB.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-WYOKA6AE.mjs → chunk-O6BH7EPN.mjs} +31 -4
- package/dist/lib/neutral/chunk-O6BH7EPN.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-KTAWP7GI.mjs → chunk-OIYW7R2G.mjs} +99 -46
- package/dist/lib/neutral/chunk-OIYW7R2G.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-TQQZLKB7.mjs → chunk-OYUG4FHF.mjs} +648 -1228
- package/dist/lib/neutral/chunk-OYUG4FHF.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-NQRLRYJM.mjs → chunk-Q5FKCVBC.mjs} +173 -60
- package/dist/lib/neutral/chunk-Q5FKCVBC.mjs.map +7 -0
- package/dist/lib/neutral/chunk-Q62IHV2N.mjs +41 -0
- package/dist/lib/neutral/chunk-Q62IHV2N.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-UFDK26FO.mjs → chunk-QVJDDG44.mjs} +69 -34
- package/dist/lib/neutral/chunk-QVJDDG44.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-B5OXLWZL.mjs → chunk-TFEWTY5A.mjs} +155 -129
- package/dist/lib/neutral/chunk-TFEWTY5A.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-UI6MWK5W.mjs → chunk-TTCSATUD.mjs} +1 -1
- package/dist/lib/neutral/{chunk-FZO7LQO7.mjs → chunk-VKWOFXT2.mjs} +22 -2
- package/dist/lib/neutral/{chunk-FZO7LQO7.mjs.map → chunk-VKWOFXT2.mjs.map} +1 -1
- package/dist/lib/neutral/{chunk-NXMFBIT5.mjs → chunk-ZACMEAYV.mjs} +89 -23
- package/dist/lib/neutral/chunk-ZACMEAYV.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +58 -38
- package/dist/lib/neutral/internal/index.mjs +131 -64
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/testing/index.mjs +222 -177
- package/dist/lib/neutral/testing/index.mjs.map +3 -3
- package/dist/types/src/Annotation.d.ts +108 -4
- package/dist/types/src/Annotation.d.ts.map +1 -1
- package/dist/types/src/Annotation.test.d.ts +2 -0
- package/dist/types/src/Annotation.test.d.ts.map +1 -0
- package/dist/types/src/Collection.d.ts +2 -3
- package/dist/types/src/Collection.d.ts.map +1 -1
- package/dist/types/src/Database.d.ts +56 -24
- package/dist/types/src/Database.d.ts.map +1 -1
- package/dist/types/src/Dataset.d.ts +17 -6
- package/dist/types/src/Dataset.d.ts.map +1 -1
- package/dist/types/src/Entity.d.ts +102 -26
- package/dist/types/src/Entity.d.ts.map +1 -1
- package/dist/types/src/Err.d.ts +27 -27
- package/dist/types/src/Err.d.ts.map +1 -1
- package/dist/types/src/Feed.d.ts +89 -25
- package/dist/types/src/Feed.d.ts.map +1 -1
- package/dist/types/src/Filter.d.ts +74 -11
- package/dist/types/src/Filter.d.ts.map +1 -1
- package/dist/types/src/Filter.test.d.ts +2 -0
- package/dist/types/src/Filter.test.d.ts.map +1 -0
- package/dist/types/src/Hypergraph.d.ts +14 -9
- package/dist/types/src/Hypergraph.d.ts.map +1 -1
- package/dist/types/src/Json.d.ts +33 -0
- package/dist/types/src/Json.d.ts.map +1 -0
- package/dist/types/src/Json.test.d.ts +2 -0
- package/dist/types/src/Json.test.d.ts.map +1 -0
- package/dist/types/src/JsonSchema.d.ts +2 -2
- package/dist/types/src/JsonSchema.d.ts.map +1 -1
- package/dist/types/src/Key.d.ts +1 -1
- package/dist/types/src/Key.d.ts.map +1 -1
- package/dist/types/src/Migration.d.ts +72 -0
- package/dist/types/src/Migration.d.ts.map +1 -0
- package/dist/types/src/Obj.d.ts +108 -65
- package/dist/types/src/Obj.d.ts.map +1 -1
- package/dist/types/src/Order.d.ts.map +1 -1
- package/dist/types/src/Query.d.ts +35 -10
- package/dist/types/src/Query.d.ts.map +1 -1
- package/dist/types/src/QueryResult.d.ts +9 -0
- package/dist/types/src/QueryResult.d.ts.map +1 -1
- package/dist/types/src/Ref.d.ts +15 -7
- package/dist/types/src/Ref.d.ts.map +1 -1
- package/dist/types/src/Registry.d.ts +131 -0
- package/dist/types/src/Registry.d.ts.map +1 -0
- package/dist/types/src/Relation.d.ts +72 -44
- package/dist/types/src/Relation.d.ts.map +1 -1
- package/dist/types/src/Scope.d.ts +34 -0
- package/dist/types/src/Scope.d.ts.map +1 -0
- package/dist/types/src/StateMap.d.ts +32 -0
- package/dist/types/src/StateMap.d.ts.map +1 -0
- package/dist/types/src/StateMap.test.d.ts +2 -0
- package/dist/types/src/StateMap.test.d.ts.map +1 -0
- package/dist/types/src/Tag.d.ts +21 -5
- package/dist/types/src/Tag.d.ts.map +1 -1
- package/dist/types/src/TagIndex.d.ts +36 -0
- package/dist/types/src/TagIndex.d.ts.map +1 -0
- package/dist/types/src/TagIndex.test.d.ts +2 -0
- package/dist/types/src/TagIndex.test.d.ts.map +1 -0
- package/dist/types/src/Tagging.d.ts +31 -0
- package/dist/types/src/Tagging.d.ts.map +1 -0
- package/dist/types/src/Type.d.ts +357 -96
- package/dist/types/src/Type.d.ts.map +1 -1
- package/dist/types/src/View.d.ts +2 -5
- package/dist/types/src/View.d.ts.map +1 -1
- package/dist/types/src/exemplars.test.d.ts +2 -0
- package/dist/types/src/exemplars.test.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +8 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/annotations.d.ts +79 -37
- package/dist/types/src/internal/Annotation/annotations.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/dictionary.d.ts +24 -0
- package/dist/types/src/internal/Annotation/dictionary.d.ts.map +1 -0
- package/dist/types/src/internal/Annotation/entity-dictionary.d.ts +14 -0
- package/dist/types/src/internal/Annotation/entity-dictionary.d.ts.map +1 -0
- package/dist/types/src/internal/Annotation/index.d.ts +4 -2
- package/dist/types/src/internal/Annotation/index.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/sorting.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/util.d.ts +14 -5
- package/dist/types/src/internal/Annotation/util.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/api.d.ts +3 -3
- package/dist/types/src/internal/Entity/api.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/entity.d.ts +72 -8
- package/dist/types/src/internal/Entity/entity.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/guard.d.ts +10 -0
- package/dist/types/src/internal/Entity/guard.d.ts.map +1 -0
- package/dist/types/src/internal/Entity/index.d.ts +2 -0
- package/dist/types/src/internal/Entity/index.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/model.d.ts +20 -17
- package/dist/types/src/internal/Entity/model.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/object.d.ts +3 -3
- package/dist/types/src/internal/Entity/object.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/relation.d.ts +30 -7
- package/dist/types/src/internal/Entity/relation.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/type-kind.d.ts +24 -0
- package/dist/types/src/internal/Entity/type-kind.d.ts.map +1 -0
- package/dist/types/src/internal/Entity/type-uri.d.ts +25 -0
- package/dist/types/src/internal/Entity/type-uri.d.ts.map +1 -0
- package/dist/types/src/internal/Entity/version.d.ts.map +1 -1
- package/dist/types/src/internal/Format/date.d.ts.map +1 -1
- package/dist/types/src/internal/Format/format.d.ts +3 -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/number.d.ts.map +1 -1
- package/dist/types/src/internal/Format/object.d.ts +3 -1
- package/dist/types/src/internal/Format/object.d.ts.map +1 -1
- package/dist/types/src/internal/Format/types.d.ts.map +1 -1
- package/dist/types/src/internal/JsonSchema/json-schema-normalize.d.ts.map +1 -1
- package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts +28 -28
- package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts.map +1 -1
- package/dist/types/src/internal/JsonSchema/json-schema.d.ts +3 -2
- package/dist/types/src/internal/JsonSchema/json-schema.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/clone.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/common.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/create-object.d.ts +11 -12
- package/dist/types/src/internal/Obj/create-object.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/deleted.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/index.d.ts +0 -1
- package/dist/types/src/internal/Obj/index.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/json-serializer.d.ts +11 -10
- package/dist/types/src/internal/Obj/json-serializer.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/set-value.d.ts +1 -1
- package/dist/types/src/internal/Obj/set-value.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/snapshot.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/typed-object.d.ts +1 -1
- package/dist/types/src/internal/Query.d.ts +10 -0
- package/dist/types/src/internal/Query.d.ts.map +1 -0
- package/dist/types/src/internal/Ref/ref-array.d.ts +2 -2
- package/dist/types/src/internal/Ref/ref-array.d.ts.map +1 -1
- package/dist/types/src/internal/Ref/ref.d.ts +42 -19
- package/dist/types/src/internal/Ref/ref.d.ts.map +1 -1
- package/dist/types/src/internal/Type/compose.d.ts.map +1 -1
- package/dist/types/src/internal/Type/index.d.ts +1 -2
- package/dist/types/src/internal/Type/index.d.ts.map +1 -1
- package/dist/types/src/internal/Type/manipulation.d.ts +0 -1
- package/dist/types/src/internal/Type/manipulation.d.ts.map +1 -1
- package/dist/types/src/internal/Type/type-schema.d.ts +52 -0
- package/dist/types/src/internal/Type/type-schema.d.ts.map +1 -0
- package/dist/types/src/internal/common/api/meta.d.ts +14 -11
- package/dist/types/src/internal/common/api/meta.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/change-context.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/change-context.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/define-hidden-property.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/errors.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/errors.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/event-batch.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/json-serializer.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/make-object.d.ts +11 -5
- package/dist/types/src/internal/common/proxy/make-object.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/ownership.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/proxy-utils.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/reactive-array.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/reactive.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/reactive.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/reactive.test.d.ts +2 -0
- package/dist/types/src/internal/common/proxy/reactive.test.d.ts.map +1 -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 +18 -2
- package/dist/types/src/internal/common/proxy/typed-handler.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/base.d.ts +4 -4
- package/dist/types/src/internal/common/types/base.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/entity.d.ts +63 -6
- package/dist/types/src/internal/common/types/entity.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/index.d.ts +1 -1
- package/dist/types/src/internal/common/types/index.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/meta.d.ts +23 -7
- package/dist/types/src/internal/common/types/meta.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/model-symbols.d.ts +8 -4
- package/dist/types/src/internal/common/types/model-symbols.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/typename.d.ts +7 -0
- package/dist/types/src/internal/common/types/typename.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/version.d.ts +1 -1
- package/dist/types/src/internal/common/types/well-known-types.d.ts +11 -0
- package/dist/types/src/internal/common/types/well-known-types.d.ts.map +1 -0
- package/dist/types/src/internal/index.d.ts +2 -0
- package/dist/types/src/internal/index.d.ts.map +1 -1
- package/dist/types/src/testing/test-data.d.ts +8 -8
- package/dist/types/src/testing/test-data.d.ts.map +1 -1
- package/dist/types/src/testing/test-schema.d.ts +83 -89
- package/dist/types/src/testing/test-schema.d.ts.map +1 -1
- package/dist/types/src/testing/util.d.ts +5 -3
- package/dist/types/src/testing/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +27 -19
- package/src/Annotation.test.ts +439 -0
- package/src/Annotation.ts +152 -4
- package/src/Collection.ts +6 -5
- package/src/Database.ts +117 -57
- package/src/Dataset.ts +10 -2
- package/src/Entity.test.ts +116 -6
- package/src/Entity.ts +130 -31
- package/src/Err.ts +4 -4
- package/src/Feed.ts +138 -43
- package/src/Filter.test.ts +90 -0
- package/src/Filter.ts +143 -27
- package/src/Hypergraph.ts +14 -9
- package/src/Json.test.ts +175 -0
- package/src/Json.ts +103 -0
- package/src/Key.ts +1 -1
- package/src/Migration.ts +114 -0
- package/src/Obj.test.ts +122 -19
- package/src/Obj.ts +279 -97
- package/src/Query.test.ts +317 -131
- package/src/Query.ts +181 -73
- package/src/QueryResult.ts +11 -0
- package/src/Ref.ts +22 -4
- package/src/Registry.ts +155 -0
- package/src/Relation.test.ts +10 -10
- package/src/Relation.ts +112 -71
- package/src/Scope.ts +50 -0
- package/src/StateMap.test.ts +56 -0
- package/src/StateMap.ts +99 -0
- package/src/Tag.md +88 -0
- package/src/Tag.ts +49 -6
- package/src/TagIndex.test.ts +57 -0
- package/src/TagIndex.ts +110 -0
- package/src/Tagging.ts +83 -0
- package/src/Type.test.ts +223 -18
- package/src/Type.ts +602 -132
- package/src/View.ts +11 -15
- package/src/exemplars.test.ts +21 -0
- package/src/index.ts +9 -3
- package/src/internal/Annotation/annotations.test.ts +82 -13
- package/src/internal/Annotation/annotations.ts +153 -115
- package/src/internal/Annotation/dictionary.ts +47 -0
- package/src/internal/Annotation/entity-dictionary.ts +40 -0
- package/src/internal/Annotation/index.ts +4 -2
- package/src/internal/Annotation/sorting.ts +0 -1
- package/src/internal/Annotation/util.ts +17 -8
- package/src/internal/Entity/api.ts +7 -8
- package/src/internal/Entity/entity.ts +196 -47
- package/src/internal/Entity/guard.ts +26 -0
- package/src/internal/Entity/index.ts +2 -0
- package/src/internal/Entity/model.ts +37 -28
- package/src/internal/Entity/object.ts +21 -6
- package/src/internal/Entity/relation.ts +68 -34
- package/src/internal/Entity/type-kind.ts +75 -0
- package/src/internal/Entity/type-uri.ts +87 -0
- package/src/internal/Entity/util.ts +10 -9
- package/src/internal/Entity/version.ts +0 -1
- package/src/internal/Format/date.test.ts +0 -1
- package/src/internal/Format/date.ts +0 -4
- package/src/internal/Format/format.test.ts +21 -1
- package/src/internal/Format/index.ts +2 -3
- package/src/internal/Format/object.ts +21 -4
- package/src/internal/Format/types.ts +1 -1
- package/src/internal/JsonSchema/annotations.ts +1 -1
- package/src/internal/JsonSchema/json-schema-type.ts +1 -1
- package/src/internal/JsonSchema/json-schema.test.ts +55 -142
- package/src/internal/JsonSchema/json-schema.ts +44 -31
- package/src/internal/Obj/clone.ts +9 -4
- package/src/internal/Obj/create-object.test.ts +13 -13
- package/src/internal/Obj/create-object.ts +68 -24
- package/src/internal/Obj/deleted.ts +1 -1
- package/src/internal/Obj/index.ts +0 -1
- package/src/internal/Obj/inspect.ts +4 -3
- package/src/internal/Obj/json-serializer.test.ts +102 -24
- package/src/internal/Obj/json-serializer.ts +105 -43
- package/src/internal/Obj/set-value.test.ts +31 -54
- package/src/internal/Obj/set-value.ts +1 -1
- package/src/internal/Obj/snapshot.ts +11 -4
- package/src/internal/Obj/typed-object.test.ts +9 -11
- package/src/internal/Obj/typed-object.ts +1 -1
- package/src/internal/Query.ts +159 -0
- package/src/internal/Ref/ref-array.ts +3 -4
- package/src/internal/Ref/ref.test.ts +17 -27
- package/src/internal/Ref/ref.ts +124 -59
- package/src/internal/Type/compose.test.ts +3 -2
- package/src/internal/Type/index.ts +1 -2
- package/src/internal/Type/manipulation.ts +0 -25
- package/src/internal/Type/type-schema.ts +60 -0
- package/src/internal/common/README.md +2 -2
- package/src/internal/common/api/meta.ts +19 -17
- package/src/internal/common/proxy/change-context.ts +1 -1
- package/src/internal/common/proxy/change.test.ts +118 -110
- package/src/internal/common/proxy/errors.ts +2 -2
- package/src/internal/common/proxy/handler.test.ts +1 -3
- package/src/internal/common/proxy/json-serializer.ts +26 -16
- package/src/internal/common/proxy/make-object.ts +43 -21
- package/src/internal/common/proxy/ownership.ts +2 -3
- package/src/internal/common/proxy/reactive-array.ts +1 -1
- package/src/internal/common/proxy/reactive.test.ts +54 -0
- package/src/internal/common/proxy/reactive.ts +11 -3
- package/src/internal/common/proxy/schema.test.ts +48 -86
- package/src/internal/common/proxy/typed-handler.test.ts +12 -12
- package/src/internal/common/proxy/typed-handler.ts +79 -19
- package/src/internal/common/proxy/typed-object.test.ts +16 -29
- package/src/internal/common/types/base.ts +4 -4
- package/src/internal/common/types/entity.ts +81 -2
- package/src/internal/common/types/index.ts +6 -1
- package/src/internal/common/types/meta.ts +49 -15
- package/src/internal/common/types/model-symbols.ts +16 -4
- package/src/internal/common/types/typename.ts +39 -3
- package/src/internal/common/types/well-known-types.ts +15 -0
- package/src/internal/index.ts +6 -0
- package/src/testing/api.test.ts +15 -10
- package/src/testing/test-data.ts +159 -100
- package/src/testing/test-schema.ts +22 -58
- package/src/testing/util.ts +14 -11
- package/dist/lib/neutral/SchemaRegistry.mjs +0 -2
- package/dist/lib/neutral/chunk-43Y5DOS6.mjs.map +0 -7
- package/dist/lib/neutral/chunk-724GQYEN.mjs +0 -56
- package/dist/lib/neutral/chunk-724GQYEN.mjs.map +0 -7
- package/dist/lib/neutral/chunk-ANHVGJI4.mjs.map +0 -7
- package/dist/lib/neutral/chunk-B5OXLWZL.mjs.map +0 -7
- package/dist/lib/neutral/chunk-BNCCGLJN.mjs +0 -7
- package/dist/lib/neutral/chunk-BNCCGLJN.mjs.map +0 -7
- package/dist/lib/neutral/chunk-BOZZPUXE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-CIRHIEMW.mjs.map +0 -7
- package/dist/lib/neutral/chunk-DYDJBZEG.mjs +0 -102
- package/dist/lib/neutral/chunk-DYDJBZEG.mjs.map +0 -7
- package/dist/lib/neutral/chunk-FXEG7EOK.mjs.map +0 -7
- package/dist/lib/neutral/chunk-KTAWP7GI.mjs.map +0 -7
- package/dist/lib/neutral/chunk-NEGC54NE.mjs +0 -130
- package/dist/lib/neutral/chunk-NEGC54NE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-NQRLRYJM.mjs.map +0 -7
- package/dist/lib/neutral/chunk-NXMFBIT5.mjs.map +0 -7
- package/dist/lib/neutral/chunk-OENWMTE6.mjs +0 -45
- package/dist/lib/neutral/chunk-OENWMTE6.mjs.map +0 -7
- package/dist/lib/neutral/chunk-OMUPQMLR.mjs.map +0 -7
- package/dist/lib/neutral/chunk-RMLF7JOZ.mjs +0 -97
- package/dist/lib/neutral/chunk-RMLF7JOZ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-SEMVAGBM.mjs +0 -355
- package/dist/lib/neutral/chunk-SEMVAGBM.mjs.map +0 -7
- package/dist/lib/neutral/chunk-TQQZLKB7.mjs.map +0 -7
- package/dist/lib/neutral/chunk-UBEZSGXY.mjs.map +0 -7
- package/dist/lib/neutral/chunk-UFDK26FO.mjs.map +0 -7
- package/dist/lib/neutral/chunk-VA2F47ZC.mjs +0 -152
- package/dist/lib/neutral/chunk-VA2F47ZC.mjs.map +0 -7
- package/dist/lib/neutral/chunk-WYOKA6AE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-YWXWXIE5.mjs.map +0 -7
- package/dist/types/src/SchemaRegistry.d.ts +0 -84
- package/dist/types/src/SchemaRegistry.d.ts.map +0 -1
- package/dist/types/src/internal/Obj/ids.d.ts +0 -6
- package/dist/types/src/internal/Obj/ids.d.ts.map +0 -1
- package/dist/types/src/internal/Type/echo-schema.d.ts +0 -181
- package/dist/types/src/internal/Type/echo-schema.d.ts.map +0 -1
- package/dist/types/src/internal/Type/persistent-schema.d.ts +0 -20
- package/dist/types/src/internal/Type/persistent-schema.d.ts.map +0 -1
- package/src/SchemaRegistry.ts +0 -106
- package/src/internal/Obj/ids.ts +0 -12
- package/src/internal/Type/echo-schema.ts +0 -424
- package/src/internal/Type/persistent-schema.ts +0 -33
- /package/dist/lib/neutral/{SchemaRegistry.mjs.map → Migration.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-UTBRYVQC.mjs.map → chunk-G6CFWUYH.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-UI6MWK5W.mjs.map → chunk-TTCSATUD.mjs.map} +0 -0
package/src/Json.ts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { EID } from '@dxos/keys';
|
|
6
|
+
|
|
7
|
+
import * as Database from './Database';
|
|
8
|
+
import * as Obj from './Obj';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* `JSON.stringify` replacer signature.
|
|
12
|
+
*
|
|
13
|
+
* Defined here (rather than re-imported from a UI package) so other ECHO-aware utilities can
|
|
14
|
+
* share a stable signature without creating a dependency edge into the UI tree.
|
|
15
|
+
*/
|
|
16
|
+
export type JsonReplacer = (key: string, value: any) => any;
|
|
17
|
+
|
|
18
|
+
export type CreateRefReplacerOptions = {
|
|
19
|
+
db: Database.Database;
|
|
20
|
+
/** How many ref hops to follow. `0` leaves all refs as-is. Default: `1`. */
|
|
21
|
+
depth?: number;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const isEncodedRef = (value: unknown): value is { '/': string } =>
|
|
25
|
+
typeof value === 'object' &&
|
|
26
|
+
value !== null &&
|
|
27
|
+
Object.keys(value as object).length === 1 &&
|
|
28
|
+
typeof (value as { '/': unknown })['/'] === 'string';
|
|
29
|
+
|
|
30
|
+
const toJson = (obj: Obj.Any): unknown => (typeof (obj as any).toJSON === 'function' ? (obj as any).toJSON() : obj);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Returns a {@link JsonReplacer} that inlines ECHO ref objects (`{ "/": "dxn:echo:..." }`) up to
|
|
34
|
+
* `depth` ref hops. Beyond that depth refs are left in their encoded form.
|
|
35
|
+
*
|
|
36
|
+
* Implemented as a per-call `JSON.stringify` replacer (not a one-shot tree walk at root) so it
|
|
37
|
+
* composes with wrappers like `safeStringify` that intercept the root call. JSON.stringify
|
|
38
|
+
* already drives the recursion; we only need to (a) detect a ref at the current callback,
|
|
39
|
+
* (b) resolve and return the target if hop budget remains, and (c) tag the returned object
|
|
40
|
+
* with its hop count so children know how far in they are.
|
|
41
|
+
*
|
|
42
|
+
* The hop count is tracked per-object via a `WeakMap`: a ref-resolved target's children inherit
|
|
43
|
+
* `parentHops + 1`; a regular intermediate object's children inherit `parentHops`. This makes the
|
|
44
|
+
* budget count *ref hops*, not tree depth — a ref deep in a tree still resolves once when
|
|
45
|
+
* `depth >= 1`.
|
|
46
|
+
*
|
|
47
|
+
* Note: ECHO objects' `toJSON` runs before the replacer is invoked, so by the time we see a
|
|
48
|
+
* value refs are already encoded as `{ "/": "dxn:..." }`.
|
|
49
|
+
*/
|
|
50
|
+
export const createRefReplacer = ({ db, depth = 1 }: CreateRefReplacerOptions): JsonReplacer => {
|
|
51
|
+
// Per-object hop count. Set when we return an object (via ref resolution or pass-through) so
|
|
52
|
+
// the child callbacks (which carry that object as `this`) can read it.
|
|
53
|
+
const hops = new WeakMap<object, number>();
|
|
54
|
+
|
|
55
|
+
return function (this: any, key: string, value: any) {
|
|
56
|
+
// Hop count for this call: hops at the parent, or 0 for the root.
|
|
57
|
+
const parentHops = this && typeof this === 'object' ? (hops.get(this) ?? 0) : 0;
|
|
58
|
+
if (isEncodedRef(value)) {
|
|
59
|
+
if (parentHops >= depth) {
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// The `{ '/': string }` shape is shared with non-DXN IPLD-style refs (e.g. CIDs);
|
|
64
|
+
// an unparseable string would otherwise crash the whole `JSON.stringify`.
|
|
65
|
+
// Treat any parse miss as "leave as-is" rather than propagating.
|
|
66
|
+
const dxnString = value['/'];
|
|
67
|
+
if (!dxnString.startsWith('dxn:') && !dxnString.startsWith('echo:')) {
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let echoUri: string | undefined;
|
|
72
|
+
try {
|
|
73
|
+
const parsed = EID.tryParse(dxnString);
|
|
74
|
+
echoUri = parsed ? EID.getEntityId(parsed) : undefined;
|
|
75
|
+
} catch {
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!echoUri) {
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
const target = db.getObjectById(echoUri);
|
|
83
|
+
if (!target) {
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const encoded = toJson(target);
|
|
88
|
+
if (encoded != null && typeof encoded === 'object') {
|
|
89
|
+
// Children of the resolved target are one hop deeper.
|
|
90
|
+
hops.set(encoded as object, parentHops + 1);
|
|
91
|
+
}
|
|
92
|
+
return encoded;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Pass-through object: children inherit the parent's hop count (this branch doesn't burn
|
|
96
|
+
// budget).
|
|
97
|
+
if (value != null && typeof value === 'object') {
|
|
98
|
+
hops.set(value, parentHops);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return value;
|
|
102
|
+
};
|
|
103
|
+
};
|
package/src/Key.ts
CHANGED
package/src/Migration.ts
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
// @import-as-namespace
|
|
6
|
+
|
|
7
|
+
import type * as Schema from 'effect/Schema';
|
|
8
|
+
|
|
9
|
+
import { type URI } from '@dxos/keys';
|
|
10
|
+
|
|
11
|
+
import type * as Database from './Database';
|
|
12
|
+
import type * as Entity from './Entity';
|
|
13
|
+
import { MetaId, type EntityMeta, getSchemaURI } from './internal';
|
|
14
|
+
import * as Type from './Type';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Result returned by a migration's `transform` callback.
|
|
18
|
+
* The data shape matches the target schema; the optional `[Obj.Meta]` symbol key lets the
|
|
19
|
+
* transform update the object's meta (e.g. `key` / `version`) atomically with the data swap.
|
|
20
|
+
*/
|
|
21
|
+
type MigrationSchemaInput = Type.AnyEntity;
|
|
22
|
+
|
|
23
|
+
type MigrationInstanceType<S> = S extends Type.AnyEntity
|
|
24
|
+
? Type.InstanceType<S>
|
|
25
|
+
: S extends Schema.Schema.AnyNoContext
|
|
26
|
+
? Schema.Schema.Type<S>
|
|
27
|
+
: never;
|
|
28
|
+
|
|
29
|
+
export type TransformResult<To> = Omit<MigrationInstanceType<To>, 'id' | Entity.KindId> & {
|
|
30
|
+
[MetaId]?: Partial<EntityMeta>;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
type DefineObjectMigrationOptions<From extends MigrationSchemaInput, To extends MigrationSchemaInput> = {
|
|
34
|
+
from: From;
|
|
35
|
+
to: To;
|
|
36
|
+
/**
|
|
37
|
+
* Pure function that converts the old object data to the new object data.
|
|
38
|
+
*
|
|
39
|
+
* The returned object may include an optional `[Obj.Meta]` entry to update the object's meta
|
|
40
|
+
* (e.g. registry `key` / `version`) atomically with the data swap.
|
|
41
|
+
*/
|
|
42
|
+
// TODO(dmaretskyi): `id` should not be a part of the schema.
|
|
43
|
+
transform: (from: MigrationInstanceType<From>, context: ObjectMigrationContext) => Promise<TransformResult<To>>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Callback that is called after the object is migrated. Called for every object that is migrated.
|
|
47
|
+
*
|
|
48
|
+
* NOTE: Database mutations performed in this callback are not guaranteed to be idempotent.
|
|
49
|
+
* If multiple peers run the migration separately, the effects may be applied multiple times.
|
|
50
|
+
*/
|
|
51
|
+
onMigration?: (params: OnMigrateProps<From, To>) => Promise<void>;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Context passed to object migration callbacks.
|
|
56
|
+
*/
|
|
57
|
+
export type ObjectMigrationContext = {
|
|
58
|
+
db: Database.Database;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
type OnMigrateProps<From, To> = {
|
|
62
|
+
before: MigrationInstanceType<From>;
|
|
63
|
+
object: MigrationInstanceType<To>;
|
|
64
|
+
db: Database.Database;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Definition of a migration from one object schema version to another.
|
|
69
|
+
*/
|
|
70
|
+
export type ObjectMigration = {
|
|
71
|
+
fromType: URI.URI;
|
|
72
|
+
toType: URI.URI;
|
|
73
|
+
fromSchema: Schema.Schema.AnyNoContext;
|
|
74
|
+
toSchema: Schema.Schema.AnyNoContext;
|
|
75
|
+
transform: (from: unknown, context: ObjectMigrationContext) => Promise<unknown>;
|
|
76
|
+
onMigration?: (params: OnMigrateProps<any, any>) => Promise<void>;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Define a migration between two object schemas.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* const migration = Migration.define({
|
|
85
|
+
* from: ContactV1,
|
|
86
|
+
* to: ContactV2,
|
|
87
|
+
* transform: async (from) => ({ name: `${from.firstName} ${from.lastName}` }),
|
|
88
|
+
* onMigration: async () => {},
|
|
89
|
+
* });
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export const define = <From extends MigrationSchemaInput, To extends MigrationSchemaInput>(
|
|
93
|
+
options: DefineObjectMigrationOptions<From, To>,
|
|
94
|
+
): ObjectMigration => {
|
|
95
|
+
const fromSchema = Type.getSchema(options.from);
|
|
96
|
+
const toSchema = Type.getSchema(options.to);
|
|
97
|
+
const fromType = getSchemaURI(fromSchema);
|
|
98
|
+
if (!fromType) {
|
|
99
|
+
throw new Error('Invalid from schema');
|
|
100
|
+
}
|
|
101
|
+
const toType = getSchemaURI(toSchema);
|
|
102
|
+
if (!toType) {
|
|
103
|
+
throw new Error('Invalid to schema');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
fromType,
|
|
108
|
+
toType,
|
|
109
|
+
fromSchema,
|
|
110
|
+
toSchema,
|
|
111
|
+
transform: options.transform as any,
|
|
112
|
+
onMigration: options.onMigration as any,
|
|
113
|
+
};
|
|
114
|
+
};
|
package/src/Obj.test.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2026 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { describe, expectTypeOf, test } from 'vitest';
|
|
5
|
+
import { describe, expectTypeOf, test, expect } from 'vitest';
|
|
6
6
|
|
|
7
7
|
import * as Entity from './Entity';
|
|
8
8
|
import { SnapshotKindId } from './internal';
|
|
@@ -42,8 +42,8 @@ describe('Obj', () => {
|
|
|
42
42
|
const snapshot = Obj.getSnapshot(obj);
|
|
43
43
|
|
|
44
44
|
// getDXN - works with both.
|
|
45
|
-
expect(Obj.
|
|
46
|
-
expect(Obj.
|
|
45
|
+
expect(Obj.getURI(obj)).toBeDefined();
|
|
46
|
+
expect(Obj.getURI(snapshot)).toBeDefined();
|
|
47
47
|
|
|
48
48
|
// getTypename - works with both.
|
|
49
49
|
expect(Obj.getTypename(obj)).toBe('com.example.type.person');
|
|
@@ -80,6 +80,17 @@ describe('Obj', () => {
|
|
|
80
80
|
expect(SnapshotKindId in snapshot).toBe(true);
|
|
81
81
|
expect(Entity.KindId in snapshot).toBe(false);
|
|
82
82
|
});
|
|
83
|
+
|
|
84
|
+
test('getSnapshot preserves parent', ({ expect }) => {
|
|
85
|
+
const parent = Obj.make(TestSchema.Organization, { name: 'parent' });
|
|
86
|
+
const child = Obj.make(TestSchema.Person, { name: 'child' });
|
|
87
|
+
Obj.setParent(child, parent);
|
|
88
|
+
|
|
89
|
+
const snapshot = Obj.getSnapshot(child);
|
|
90
|
+
|
|
91
|
+
expect(Obj.getParent(child)).toBe(parent);
|
|
92
|
+
expect(Obj.getParent(snapshot)).toBe(parent);
|
|
93
|
+
});
|
|
83
94
|
});
|
|
84
95
|
|
|
85
96
|
describe('snapshotOf', () => {
|
|
@@ -117,8 +128,8 @@ describe('Obj', () => {
|
|
|
117
128
|
|
|
118
129
|
test('returns keys from reactive object and snapshot', ({ expect }) => {
|
|
119
130
|
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
120
|
-
Obj.
|
|
121
|
-
const meta = Obj.getMeta(
|
|
131
|
+
Obj.update(obj, (obj) => {
|
|
132
|
+
const meta = Obj.getMeta(obj);
|
|
122
133
|
meta.keys.push({ source: SOURCE, id: 'key-1' });
|
|
123
134
|
meta.keys.push({ source: SOURCE, id: 'key-2' });
|
|
124
135
|
meta.keys.push({ source: 'other', id: 'key-3' });
|
|
@@ -134,7 +145,7 @@ describe('Obj', () => {
|
|
|
134
145
|
|
|
135
146
|
test('throws for plain object without metadata', ({ expect }) => {
|
|
136
147
|
const plain = { id: 'plain-1', name: 'Plain' };
|
|
137
|
-
expect(() => Obj.getKeys(plain as any, SOURCE)).toThrow(/
|
|
148
|
+
expect(() => Obj.getKeys(plain as any, SOURCE)).toThrow(/EntityMeta not found/);
|
|
138
149
|
});
|
|
139
150
|
});
|
|
140
151
|
|
|
@@ -166,8 +177,8 @@ describe('Obj', () => {
|
|
|
166
177
|
|
|
167
178
|
const cloned = Obj.clone(original);
|
|
168
179
|
|
|
169
|
-
Obj.
|
|
170
|
-
|
|
180
|
+
Obj.update(original, (original) => {
|
|
181
|
+
original.name = 'Bob';
|
|
171
182
|
});
|
|
172
183
|
|
|
173
184
|
expect(original.name).toBe('Bob');
|
|
@@ -206,8 +217,8 @@ describe('Obj', () => {
|
|
|
206
217
|
expect(cloned.employer?.target).toBe(person.employer?.target);
|
|
207
218
|
|
|
208
219
|
// Modifying the referenced object affects both
|
|
209
|
-
Obj.
|
|
210
|
-
|
|
220
|
+
Obj.update(employer, (employer) => {
|
|
221
|
+
employer.name = 'Updated DXOS';
|
|
211
222
|
});
|
|
212
223
|
|
|
213
224
|
expect(cloned.employer?.target?.name).toBe('Updated DXOS');
|
|
@@ -234,8 +245,8 @@ describe('Obj', () => {
|
|
|
234
245
|
expect(cloned.employer?.target?.name).toBe(employer.name);
|
|
235
246
|
|
|
236
247
|
// Modifying the original referenced object does not affect the clone
|
|
237
|
-
Obj.
|
|
238
|
-
|
|
248
|
+
Obj.update(employer, (employer) => {
|
|
249
|
+
employer.name = 'Updated DXOS';
|
|
239
250
|
});
|
|
240
251
|
|
|
241
252
|
expect(cloned.employer?.target?.name).toBe('DXOS');
|
|
@@ -329,12 +340,12 @@ describe('Obj', () => {
|
|
|
329
340
|
expect(cloned.address?.city).toBe('San Francisco');
|
|
330
341
|
expect(cloned.address?.state).toBe('CA');
|
|
331
342
|
expect(cloned.address?.zip).toBe('94102');
|
|
332
|
-
expect(cloned.address?.coordinates
|
|
333
|
-
expect(cloned.address?.coordinates
|
|
343
|
+
expect(cloned.address?.coordinates?.lat).toBe(37.7749);
|
|
344
|
+
expect(cloned.address?.coordinates?.lng).toBe(-122.4194);
|
|
334
345
|
|
|
335
346
|
// Modifying nested properties should be independent
|
|
336
|
-
Obj.
|
|
337
|
-
|
|
347
|
+
Obj.update(person, (person) => {
|
|
348
|
+
person.address!.city = 'New York';
|
|
338
349
|
});
|
|
339
350
|
|
|
340
351
|
expect(cloned.address?.city).toBe('San Francisco');
|
|
@@ -366,8 +377,8 @@ describe('Obj', () => {
|
|
|
366
377
|
expect(cloned.tasks?.[2]?.target).not.toBe(task3);
|
|
367
378
|
|
|
368
379
|
// Modifying original tasks should not affect cloned ones
|
|
369
|
-
Obj.
|
|
370
|
-
|
|
380
|
+
Obj.update(task1, (task1) => {
|
|
381
|
+
task1.title = 'Updated Task 1';
|
|
371
382
|
});
|
|
372
383
|
|
|
373
384
|
expect(cloned.tasks?.[0]?.target?.title).toBe('Task 1');
|
|
@@ -405,7 +416,7 @@ describe('Obj', () => {
|
|
|
405
416
|
const cloned = Obj.clone(person);
|
|
406
417
|
|
|
407
418
|
expect(Obj.instanceOf(TestSchema.Person, cloned)).toBe(true);
|
|
408
|
-
expect(Obj.
|
|
419
|
+
expect(Obj.getType(cloned)).toBe(Obj.getType(person));
|
|
409
420
|
});
|
|
410
421
|
});
|
|
411
422
|
|
|
@@ -444,4 +455,96 @@ describe('Obj', () => {
|
|
|
444
455
|
expectTypeOf<Obj.Any>().toMatchTypeOf<Obj.Unknown>();
|
|
445
456
|
});
|
|
446
457
|
});
|
|
458
|
+
|
|
459
|
+
describe('Obj.updateFrom', () => {
|
|
460
|
+
test('returns false when values already match', () => {
|
|
461
|
+
const target = Obj.make(TestSchema.Organization, { name: 'Acme', properties: { region: 'EU' } });
|
|
462
|
+
const source = Obj.make(TestSchema.Organization, { name: 'Acme', properties: { region: 'EU' } });
|
|
463
|
+
Obj.update(target, (target) => {
|
|
464
|
+
expect(Obj.updateFrom(target, source)).toBe(false);
|
|
465
|
+
});
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
test('updates scalar and nested record fields on Organization', () => {
|
|
469
|
+
const target = Obj.make(TestSchema.Organization, {
|
|
470
|
+
name: 'Old',
|
|
471
|
+
properties: { a: '1' },
|
|
472
|
+
});
|
|
473
|
+
const source = Obj.make(TestSchema.Organization, {
|
|
474
|
+
name: 'New',
|
|
475
|
+
properties: { a: '2', b: '3' },
|
|
476
|
+
});
|
|
477
|
+
Obj.update(target, (target) => {
|
|
478
|
+
expect(Obj.updateFrom(target, source)).toBe(true);
|
|
479
|
+
});
|
|
480
|
+
expect(target.name).toBe('New');
|
|
481
|
+
expect(target.properties).toEqual({ a: '2', b: '3' });
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
test('compares employer refs by DXN and updates Person fields', () => {
|
|
485
|
+
const orgA = Obj.make(TestSchema.Organization, { name: 'A' });
|
|
486
|
+
const orgB = Obj.make(TestSchema.Organization, { name: 'B' });
|
|
487
|
+
const target = Obj.make(TestSchema.Person, {
|
|
488
|
+
name: 'Ann',
|
|
489
|
+
username: 'ann',
|
|
490
|
+
email: 'ann@x.test',
|
|
491
|
+
employer: Ref.make(orgA),
|
|
492
|
+
address: { city: 'X', state: 'Y', zip: '1', coordinates: { lat: 0, lng: 0 } },
|
|
493
|
+
});
|
|
494
|
+
const source = Obj.make(TestSchema.Person, {
|
|
495
|
+
name: 'Ann',
|
|
496
|
+
username: 'ann',
|
|
497
|
+
email: 'ann@x.test',
|
|
498
|
+
employer: Ref.make(orgB),
|
|
499
|
+
address: { city: 'Portland', state: 'OR', zip: '97201', coordinates: { lat: 45.5, lng: -122.6 } },
|
|
500
|
+
});
|
|
501
|
+
Obj.update(target, (target) => {
|
|
502
|
+
expect(Obj.updateFrom(target, source)).toBe(true);
|
|
503
|
+
});
|
|
504
|
+
expect(target.employer?.uri.toString()).toBe(Ref.make(orgB).uri.toString());
|
|
505
|
+
expect(target.address?.city).toBe('Portland');
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
test('updates array of task refs when DXNs differ', () => {
|
|
509
|
+
const t1 = Obj.make(TestSchema.Task, { title: 'One' });
|
|
510
|
+
const t2 = Obj.make(TestSchema.Task, { title: 'Two' });
|
|
511
|
+
const t3 = Obj.make(TestSchema.Task, { title: 'Three' });
|
|
512
|
+
const target = Obj.make(TestSchema.Person, {
|
|
513
|
+
name: 'Bob',
|
|
514
|
+
username: 'bob',
|
|
515
|
+
email: 'bob@x.test',
|
|
516
|
+
tasks: [Ref.make(t1), Ref.make(t2)],
|
|
517
|
+
});
|
|
518
|
+
const source = Obj.make(TestSchema.Person, {
|
|
519
|
+
name: 'Bob',
|
|
520
|
+
username: 'bob',
|
|
521
|
+
email: 'bob@x.test',
|
|
522
|
+
tasks: [Ref.make(t1), Ref.make(t3)],
|
|
523
|
+
});
|
|
524
|
+
Obj.update(target, (target) => {
|
|
525
|
+
expect(Obj.updateFrom(target, source)).toBe(true);
|
|
526
|
+
});
|
|
527
|
+
expect(target.tasks?.map((r) => r.uri)).toEqual(source.tasks?.map((r) => r.uri));
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
test('respects include option', () => {
|
|
531
|
+
const target = Obj.make(TestSchema.Organization, { name: 'Keep', properties: { x: '1' } });
|
|
532
|
+
const source = Obj.make(TestSchema.Organization, { name: 'Drop', properties: { x: '2' } });
|
|
533
|
+
Obj.update(target, (target) => {
|
|
534
|
+
expect(Obj.updateFrom(target, source, { include: ['properties'] })).toBe(true);
|
|
535
|
+
});
|
|
536
|
+
expect(target.name).toBe('Keep');
|
|
537
|
+
expect(target.properties).toEqual({ x: '2' });
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
test('respects exclude option', () => {
|
|
541
|
+
const target = Obj.make(TestSchema.Organization, { name: 'Old', properties: { x: '1' } });
|
|
542
|
+
const source = Obj.make(TestSchema.Organization, { name: 'New', properties: { x: '2' } });
|
|
543
|
+
Obj.update(target, (target) => {
|
|
544
|
+
expect(Obj.updateFrom(target, source, { exclude: ['name'] })).toBe(true);
|
|
545
|
+
});
|
|
546
|
+
expect(target.name).toBe('Old');
|
|
547
|
+
expect(target.properties).toEqual({ x: '2' });
|
|
548
|
+
});
|
|
549
|
+
});
|
|
447
550
|
});
|