@dxos/echo 0.8.4-main.c85a9c8dae → 0.8.4-main.cb12b3f963
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 +3 -3
- package/dist/lib/neutral/Database.mjs +8 -4
- package/dist/lib/neutral/Entity.mjs +16 -11
- package/dist/lib/neutral/Err.mjs +1 -1
- package/dist/lib/neutral/Extension.mjs +18 -0
- package/dist/lib/neutral/Extension.mjs.map +7 -0
- package/dist/lib/neutral/Feed.mjs +21 -14
- package/dist/lib/neutral/Filter.mjs +21 -10
- package/dist/lib/neutral/Format.mjs +3 -3
- package/dist/lib/neutral/JsonSchema.mjs +8 -7
- package/dist/lib/neutral/Key.mjs +1 -1
- package/dist/lib/neutral/Migration.mjs +17 -0
- package/dist/lib/neutral/Migration.mjs.map +7 -0
- package/dist/lib/neutral/Obj.mjs +16 -10
- package/dist/lib/neutral/Order.mjs +1 -1
- package/dist/lib/neutral/Query.mjs +19 -13
- package/dist/lib/neutral/QueryResult.mjs +1 -1
- package/dist/lib/neutral/Ref.mjs +7 -7
- package/dist/lib/neutral/Relation.mjs +15 -11
- package/dist/lib/neutral/SchemaRegistry.mjs +1 -1
- package/dist/lib/neutral/Tag.mjs +14 -10
- package/dist/lib/neutral/Type.mjs +10 -7
- package/dist/lib/neutral/{chunk-ALOGSVBP.mjs → chunk-3U5PIVPZ.mjs} +59 -4
- package/dist/lib/neutral/chunk-3U5PIVPZ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-DZQSL6RW.mjs → chunk-44HT3MEC.mjs} +2 -2
- package/dist/lib/neutral/{chunk-DZQSL6RW.mjs.map → chunk-44HT3MEC.mjs.map} +1 -1
- package/dist/lib/neutral/{chunk-5ELDDYWE.mjs → chunk-4VTRFJV3.mjs} +17 -19
- package/dist/lib/neutral/chunk-4VTRFJV3.mjs.map +7 -0
- package/dist/lib/neutral/chunk-5NR2KWDU.mjs +34 -0
- package/dist/lib/neutral/chunk-5NR2KWDU.mjs.map +7 -0
- package/dist/lib/neutral/chunk-62RJTYOZ.mjs +346 -0
- package/dist/lib/neutral/chunk-62RJTYOZ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-OVUBTQLT.mjs → chunk-7OO5B5DD.mjs} +2 -2
- package/dist/lib/neutral/chunk-7OO5B5DD.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-ANHVGJI4.mjs → chunk-7RVZT53K.mjs} +1 -1
- package/dist/lib/neutral/{chunk-GAWKQ5DZ.mjs → chunk-AG7JS76F.mjs} +5 -5
- package/dist/lib/neutral/chunk-AG7JS76F.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-PP4DNUZU.mjs → chunk-AVPYX7FF.mjs} +1399 -2882
- package/dist/lib/neutral/chunk-AVPYX7FF.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-ZWKJ4LZJ.mjs → chunk-BCKTAKBX.mjs} +23 -51
- package/dist/lib/neutral/chunk-BCKTAKBX.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-T6JEFNP6.mjs → chunk-BICZKPQG.mjs} +1 -1
- package/dist/lib/neutral/{chunk-T6JEFNP6.mjs.map → chunk-BICZKPQG.mjs.map} +1 -1
- package/dist/lib/neutral/{chunk-F7KMHDPJ.mjs → chunk-GECFB2UL.mjs} +49 -31
- package/dist/lib/neutral/chunk-GECFB2UL.mjs.map +7 -0
- package/dist/lib/neutral/chunk-GWFFC34K.mjs +50 -0
- package/dist/lib/neutral/chunk-GWFFC34K.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-BRJSLACP.mjs → chunk-M7ET73JD.mjs} +71 -17
- package/dist/lib/neutral/chunk-M7ET73JD.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-4KG6IGL4.mjs → chunk-N4B7FHQT.mjs} +4 -4
- package/dist/lib/neutral/{chunk-4KG6IGL4.mjs.map → chunk-N4B7FHQT.mjs.map} +2 -2
- package/dist/lib/neutral/{chunk-KGV3QIRX.mjs → chunk-NCSIQP3L.mjs} +124 -17
- package/dist/lib/neutral/chunk-NCSIQP3L.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-QXF3LGN2.mjs → chunk-NGQNU3KX.mjs} +5 -3
- package/dist/lib/neutral/chunk-NGQNU3KX.mjs.map +7 -0
- package/dist/lib/neutral/chunk-PRCRETDK.mjs +36 -0
- package/dist/lib/neutral/chunk-PRCRETDK.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-AQP4QKYP.mjs → chunk-S4JXD2RO.mjs} +44 -9
- package/dist/lib/neutral/chunk-S4JXD2RO.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-W7OP5HGZ.mjs → chunk-SVEGO3DJ.mjs} +14 -10
- package/dist/lib/neutral/chunk-SVEGO3DJ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-M2KVTHZM.mjs → chunk-TRPZU2HV.mjs} +10 -10
- package/dist/lib/neutral/chunk-TRPZU2HV.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-ZTUBYOGB.mjs → chunk-TTCSATUD.mjs} +1 -1
- package/dist/lib/neutral/chunk-TTCSATUD.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-GFNCSK7F.mjs → chunk-TTUIJXGD.mjs} +54 -23
- package/dist/lib/neutral/chunk-TTUIJXGD.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-OMUPQMLR.mjs → chunk-V72DY6LU.mjs} +1 -1
- package/dist/lib/neutral/{chunk-T4MPQJ7X.mjs → chunk-WGMPVUUL.mjs} +6 -22
- package/dist/lib/neutral/chunk-WGMPVUUL.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-O3TZFQCT.mjs → chunk-YDRLYZKW.mjs} +2 -2
- package/dist/lib/neutral/chunk-YDRLYZKW.mjs.map +7 -0
- package/dist/lib/neutral/chunk-Z25FPDXG.mjs +734 -0
- package/dist/lib/neutral/chunk-Z25FPDXG.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-MXQJZCPY.mjs → chunk-ZISMEVKD.mjs} +1 -1
- package/dist/lib/neutral/chunk-ZISMEVKD.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +38 -25
- package/dist/lib/neutral/internal/index.mjs +48 -38
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/testing/index.mjs +41 -35
- package/dist/lib/neutral/testing/index.mjs.map +2 -2
- package/dist/types/src/Annotation.d.ts +3 -3
- package/dist/types/src/Annotation.d.ts.map +1 -1
- package/dist/types/src/Collection.d.ts.map +1 -1
- package/dist/types/src/Database.d.ts +15 -3
- package/dist/types/src/Database.d.ts.map +1 -1
- package/dist/types/src/Dataset.d.ts +2 -1
- package/dist/types/src/Dataset.d.ts.map +1 -1
- package/dist/types/src/Entity.d.ts +17 -11
- package/dist/types/src/Entity.d.ts.map +1 -1
- package/dist/types/src/Err.d.ts +18 -18
- package/dist/types/src/Err.d.ts.map +1 -1
- package/dist/types/src/Extension.d.ts +80 -0
- package/dist/types/src/Extension.d.ts.map +1 -0
- package/dist/types/src/Extension.test.d.ts +2 -0
- package/dist/types/src/Extension.test.d.ts.map +1 -0
- package/dist/types/src/Feed.d.ts +40 -23
- package/dist/types/src/Feed.d.ts.map +1 -1
- package/dist/types/src/Filter.d.ts +33 -4
- 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/Format.d.ts +1 -1
- package/dist/types/src/Format.d.ts.map +1 -1
- package/dist/types/src/Hypergraph.d.ts +6 -1
- 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 +5 -5
- package/dist/types/src/JsonSchema.d.ts.map +1 -1
- package/dist/types/src/Migration.d.ts +57 -0
- package/dist/types/src/Migration.d.ts.map +1 -0
- package/dist/types/src/Obj.d.ts +45 -29
- 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 +13 -2
- package/dist/types/src/Query.d.ts.map +1 -1
- package/dist/types/src/Ref.d.ts +11 -11
- package/dist/types/src/Ref.d.ts.map +1 -1
- package/dist/types/src/Relation.d.ts +16 -16
- package/dist/types/src/Relation.d.ts.map +1 -1
- package/dist/types/src/SchemaRegistry.d.ts +1 -1
- package/dist/types/src/Tag.d.ts +2 -2
- package/dist/types/src/Tag.d.ts.map +1 -1
- package/dist/types/src/Type.d.ts +10 -9
- package/dist/types/src/Type.d.ts.map +1 -1
- package/dist/types/src/View.d.ts +1 -1
- 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 +3 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/internal/{annotations → Annotation}/annotations.d.ts +24 -2
- package/dist/types/src/internal/Annotation/annotations.d.ts.map +1 -0
- package/dist/types/src/internal/Annotation/annotations.test.d.ts.map +1 -0
- package/dist/types/src/internal/Annotation/index.d.ts +4 -0
- package/dist/types/src/internal/Annotation/index.d.ts.map +1 -0
- package/dist/types/src/internal/{api → Annotation}/sorting.d.ts +1 -1
- package/dist/types/src/internal/Annotation/sorting.d.ts.map +1 -0
- package/dist/types/src/internal/{annotations → Annotation}/util.d.ts +2 -2
- package/dist/types/src/internal/Annotation/util.d.ts.map +1 -0
- package/dist/types/src/internal/{api/entity.d.ts → Entity/api.d.ts} +2 -2
- package/dist/types/src/internal/Entity/api.d.ts.map +1 -0
- package/dist/types/src/internal/{entities → Entity}/entity.d.ts +2 -2
- package/dist/types/src/internal/Entity/entity.d.ts.map +1 -0
- package/dist/types/src/internal/{entities → Entity}/index.d.ts +2 -0
- package/dist/types/src/internal/Entity/index.d.ts.map +1 -0
- package/dist/types/src/internal/{entities → Entity}/model.d.ts +2 -26
- package/dist/types/src/internal/Entity/model.d.ts.map +1 -0
- package/dist/types/src/internal/{entities → Entity}/object.d.ts +2 -2
- package/dist/types/src/internal/Entity/object.d.ts.map +1 -0
- package/dist/types/src/internal/{entities → Entity}/relation.d.ts +3 -30
- package/dist/types/src/internal/Entity/relation.d.ts.map +1 -0
- package/dist/types/src/internal/Entity/util.d.ts.map +1 -0
- package/dist/types/src/internal/{api → Entity}/version.d.ts +1 -1
- package/dist/types/src/internal/Entity/version.d.ts.map +1 -0
- package/dist/types/src/internal/Format/date.d.ts.map +1 -0
- package/dist/types/src/internal/Format/date.test.d.ts.map +1 -0
- package/dist/types/src/internal/Format/format.d.ts.map +1 -0
- package/dist/types/src/internal/Format/format.test.d.ts.map +1 -0
- package/dist/types/src/internal/Format/index.d.ts.map +1 -0
- package/dist/types/src/internal/Format/number.d.ts.map +1 -0
- package/dist/types/src/internal/Format/object.d.ts.map +1 -0
- package/dist/types/src/internal/Format/select.d.ts.map +1 -0
- package/dist/types/src/internal/Format/string.d.ts.map +1 -0
- package/dist/types/src/internal/{formats → Format}/types.d.ts +1 -1
- package/dist/types/src/internal/Format/types.d.ts.map +1 -0
- package/dist/types/src/internal/{json-schema → JsonSchema}/annotations.d.ts +1 -1
- package/dist/types/src/internal/JsonSchema/annotations.d.ts.map +1 -0
- package/dist/types/src/internal/JsonSchema/effect-schema.test.d.ts.map +1 -0
- package/dist/types/src/internal/JsonSchema/index.d.ts.map +1 -0
- package/dist/types/src/internal/JsonSchema/json-schema-normalize.d.ts.map +1 -0
- package/dist/types/src/internal/{json-schema → JsonSchema}/json-schema-type.d.ts +23 -23
- package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts.map +1 -0
- package/dist/types/src/internal/{json-schema → JsonSchema}/json-schema.d.ts +1 -1
- package/dist/types/src/internal/JsonSchema/json-schema.d.ts.map +1 -0
- package/dist/types/src/internal/JsonSchema/json-schema.test.d.ts.map +1 -0
- package/dist/types/src/internal/Obj/clone.d.ts.map +1 -0
- package/dist/types/src/internal/Obj/common.d.ts.map +1 -0
- package/dist/types/src/internal/{object → Obj}/create-object.d.ts +2 -2
- package/dist/types/src/internal/Obj/create-object.d.ts.map +1 -0
- package/dist/types/src/internal/Obj/create-object.test.d.ts.map +1 -0
- package/dist/types/src/internal/{object → Obj}/deleted.d.ts +1 -1
- package/dist/types/src/internal/Obj/deleted.d.ts.map +1 -0
- package/dist/types/src/internal/Obj/ids.d.ts.map +1 -0
- package/dist/types/src/internal/Obj/index.d.ts.map +1 -0
- package/dist/types/src/internal/Obj/inspect.d.ts.map +1 -0
- package/dist/types/src/internal/{object → Obj}/json-serializer.d.ts +13 -5
- package/dist/types/src/internal/Obj/json-serializer.d.ts.map +1 -0
- package/dist/types/src/internal/Obj/json-serializer.test.d.ts.map +1 -0
- package/dist/types/src/internal/Obj/schema-validator.d.ts +2 -0
- package/dist/types/src/internal/Obj/schema-validator.d.ts.map +1 -0
- package/dist/types/src/internal/Obj/schema-validator.test.d.ts.map +1 -0
- package/dist/types/src/internal/{object → Obj}/set-value.d.ts +2 -2
- package/dist/types/src/internal/Obj/set-value.d.ts.map +1 -0
- package/dist/types/src/internal/Obj/set-value.test.d.ts.map +1 -0
- package/dist/types/src/internal/Obj/snapshot.d.ts.map +1 -0
- package/dist/types/src/internal/{object → Obj}/typed-object.d.ts +2 -2
- package/dist/types/src/internal/Obj/typed-object.d.ts.map +1 -0
- package/dist/types/src/internal/Obj/typed-object.test.d.ts.map +1 -0
- 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/index.d.ts.map +1 -0
- package/dist/types/src/internal/{ref → Ref}/ref-array.d.ts +1 -1
- package/dist/types/src/internal/Ref/ref-array.d.ts.map +1 -0
- package/dist/types/src/internal/{ref → Ref}/ref.d.ts +15 -2
- package/dist/types/src/internal/Ref/ref.d.ts.map +1 -0
- package/dist/types/src/internal/Ref/ref.test.d.ts.map +1 -0
- package/dist/types/src/internal/{schema → Type}/compose.d.ts +1 -1
- package/dist/types/src/internal/Type/compose.d.ts.map +1 -0
- package/dist/types/src/internal/Type/compose.test.d.ts.map +1 -0
- package/dist/types/src/internal/{schema → Type}/echo-schema.d.ts +6 -6
- package/dist/types/src/internal/Type/echo-schema.d.ts.map +1 -0
- package/dist/types/src/internal/Type/index.d.ts.map +1 -0
- package/dist/types/src/internal/Type/manipulation.d.ts.map +1 -0
- package/dist/types/src/internal/{schema → Type}/persistent-schema.d.ts +2 -2
- package/dist/types/src/internal/Type/persistent-schema.d.ts.map +1 -0
- package/dist/types/src/internal/{api → common/api}/index.d.ts +0 -4
- package/dist/types/src/internal/common/api/index.d.ts.map +1 -0
- package/dist/types/src/internal/{api → common/api}/meta.d.ts +3 -3
- package/dist/types/src/internal/common/api/meta.d.ts.map +1 -0
- package/dist/types/src/internal/common/index.d.ts +4 -0
- package/dist/types/src/internal/common/index.d.ts.map +1 -0
- package/dist/types/src/internal/{proxy → common/proxy}/change-context.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/change-context.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/change.test.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/define-hidden-property.d.ts.map +1 -0
- package/dist/types/src/internal/{proxy → common/proxy}/errors.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/errors.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/event-batch.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/handler.test.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/index.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/json-serializer.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/make-object.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/ownership.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/proxy-types.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/proxy-utils.d.ts.map +1 -0
- package/dist/types/src/internal/{proxy → common/proxy}/reactive-array.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/reactive-array.d.ts.map +1 -0
- package/dist/types/src/internal/{proxy → common/proxy}/reactive.d.ts +2 -2
- package/dist/types/src/internal/{proxy → 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 -0
- package/dist/types/src/internal/common/proxy/schema.test.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/symbols.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/typed-handler.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/typed-handler.test.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/typed-object.test.d.ts.map +1 -0
- package/dist/types/src/internal/common/types/base.d.ts.map +1 -0
- package/dist/types/src/internal/{types → common/types}/entity.d.ts +4 -4
- package/dist/types/src/internal/common/types/entity.d.ts.map +1 -0
- package/dist/types/src/internal/{types → common/types}/index.d.ts +1 -0
- package/dist/types/src/internal/common/types/index.d.ts.map +1 -0
- package/dist/types/src/internal/{types → common/types}/meta.d.ts +3 -3
- package/dist/types/src/internal/common/types/meta.d.ts.map +1 -0
- package/dist/types/src/internal/common/types/model-symbols.d.ts +54 -0
- package/dist/types/src/internal/common/types/model-symbols.d.ts.map +1 -0
- package/dist/types/src/internal/common/types/typename.d.ts.map +1 -0
- package/dist/types/src/internal/{types → common/types}/version.d.ts +1 -1
- package/dist/types/src/internal/common/types/version.d.ts.map +1 -0
- package/dist/types/src/internal/index.d.ts +9 -10
- package/dist/types/src/internal/index.d.ts.map +1 -1
- package/dist/types/src/testing/test-data.d.ts.map +1 -1
- package/dist/types/src/testing/test-schema.d.ts +53 -53
- package/dist/types/src/testing/test-schema.d.ts.map +1 -1
- package/dist/types/src/testing/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +24 -14
- package/src/Annotation.ts +5 -3
- package/src/Collection.ts +8 -1
- package/src/Database.ts +54 -17
- package/src/Dataset.ts +2 -0
- package/src/Entity.ts +20 -11
- package/src/Err.ts +2 -0
- package/src/Extension.test.ts +235 -0
- package/src/Extension.ts +122 -0
- package/src/Feed.ts +86 -36
- package/src/Filter.test.ts +90 -0
- package/src/Filter.ts +68 -3
- package/src/Format.ts +1 -1
- package/src/Hypergraph.ts +7 -2
- package/src/Json.test.ts +175 -0
- package/src/Json.ts +102 -0
- package/src/JsonSchema.ts +7 -5
- package/src/Migration.ts +94 -0
- package/src/Obj.test.ts +107 -15
- package/src/Obj.ts +166 -40
- package/src/Order.ts +2 -0
- package/src/Query.test.ts +221 -31
- package/src/Query.ts +50 -3
- package/src/Ref.ts +14 -12
- package/src/Relation.test.ts +2 -2
- package/src/Relation.ts +28 -21
- package/src/SchemaRegistry.ts +1 -1
- package/src/Tag.ts +3 -1
- package/src/Type.ts +14 -11
- package/src/View.ts +9 -2
- package/src/exemplars.test.ts +21 -0
- package/src/index.ts +4 -0
- package/src/internal/{annotations → Annotation}/annotations.test.ts +56 -7
- package/src/internal/{annotations → Annotation}/annotations.ts +71 -20
- package/src/internal/{annotations → Annotation}/index.ts +1 -0
- package/src/internal/{api → Annotation}/sorting.ts +2 -4
- package/src/internal/{annotations → Annotation}/util.ts +1 -1
- package/src/internal/{api/entity.ts → Entity/api.ts} +3 -2
- package/src/internal/{entities → Entity}/entity.ts +2 -2
- package/src/internal/{entities → Entity}/index.ts +2 -0
- package/src/internal/{entities → Entity}/model.ts +13 -42
- package/src/internal/{entities → Entity}/object.ts +2 -3
- package/src/internal/{entities → Entity}/relation.ts +19 -36
- package/src/internal/{api → Entity}/version.ts +2 -2
- package/src/internal/{formats → Format}/date.test.ts +1 -2
- package/src/internal/{formats → Format}/format.test.ts +1 -2
- package/src/internal/{formats → Format}/types.ts +2 -2
- package/src/internal/{json-schema → JsonSchema}/annotations.ts +3 -3
- package/src/internal/{json-schema → JsonSchema}/json-schema-type.ts +4 -4
- package/src/internal/{json-schema → JsonSchema}/json-schema.test.ts +48 -49
- package/src/internal/{json-schema → JsonSchema}/json-schema.ts +3 -4
- package/src/internal/{object → Obj}/clone.ts +3 -3
- package/src/internal/{object → Obj}/common.ts +2 -2
- package/src/internal/{object → Obj}/create-object.test.ts +5 -7
- package/src/internal/{object → Obj}/create-object.ts +5 -6
- package/src/internal/{object → Obj}/deleted.ts +2 -2
- package/src/internal/{object → Obj}/inspect.ts +2 -2
- package/src/internal/{object → Obj}/json-serializer.test.ts +8 -9
- package/src/internal/{object → Obj}/json-serializer.ts +36 -18
- package/src/internal/{object → Obj}/schema-validator.ts +1 -1
- package/src/internal/{object → Obj}/set-value.test.ts +24 -24
- package/src/internal/{object → Obj}/set-value.ts +3 -3
- package/src/internal/{object → Obj}/snapshot.ts +14 -5
- package/src/internal/{object → Obj}/typed-object.test.ts +3 -3
- package/src/internal/{object → Obj}/typed-object.ts +2 -2
- package/src/internal/Query.ts +137 -0
- package/src/internal/{ref → Ref}/ref-array.ts +1 -2
- package/src/internal/{ref → Ref}/ref.test.ts +4 -5
- package/src/internal/{ref → Ref}/ref.ts +20 -3
- package/src/internal/{schema → Type}/compose.test.ts +5 -6
- package/src/internal/{schema → Type}/compose.ts +1 -1
- package/src/internal/{schema → Type}/echo-schema.ts +7 -8
- package/src/internal/{schema → Type}/manipulation.ts +1 -1
- package/src/internal/{schema → Type}/persistent-schema.ts +7 -7
- package/src/internal/{README.md → common/README.md} +1 -1
- package/src/internal/{api → common/api}/index.ts +0 -4
- package/src/internal/{api → common/api}/meta.ts +3 -3
- package/src/internal/common/index.ts +7 -0
- package/src/internal/{proxy → common/proxy}/change-context.ts +1 -1
- package/src/internal/{proxy → common/proxy}/change.test.ts +97 -97
- package/src/internal/{proxy → common/proxy}/errors.ts +2 -2
- package/src/internal/{proxy → common/proxy}/handler.test.ts +2 -4
- package/src/internal/{proxy → common/proxy}/json-serializer.ts +6 -3
- package/src/internal/{proxy → common/proxy}/make-object.ts +1 -2
- package/src/internal/{proxy → common/proxy}/ownership.ts +0 -1
- package/src/internal/{proxy → common/proxy}/reactive-array.ts +1 -1
- package/src/internal/common/proxy/reactive.test.ts +54 -0
- package/src/internal/{proxy → common/proxy}/reactive.ts +12 -4
- package/src/internal/{proxy → common/proxy}/schema.test.ts +10 -10
- package/src/internal/{proxy → common/proxy}/typed-handler.test.ts +6 -7
- package/src/internal/{proxy → common/proxy}/typed-handler.ts +10 -13
- package/src/internal/{proxy → common/proxy}/typed-object.test.ts +5 -6
- package/src/internal/{types → common/types}/entity.ts +1 -1
- package/src/internal/{types → common/types}/index.ts +1 -0
- package/src/internal/{types → common/types}/meta.ts +1 -2
- package/src/internal/common/types/model-symbols.ts +69 -0
- package/src/internal/index.ts +9 -31
- package/src/testing/api.test.ts +2 -3
- package/src/testing/test-data.ts +0 -1
- package/src/testing/test-schema.ts +9 -9
- package/dist/lib/neutral/chunk-5ELDDYWE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-ALOGSVBP.mjs.map +0 -7
- package/dist/lib/neutral/chunk-AQP4QKYP.mjs.map +0 -7
- package/dist/lib/neutral/chunk-BRJSLACP.mjs.map +0 -7
- package/dist/lib/neutral/chunk-F7KMHDPJ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-GAWKQ5DZ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-GFNCSK7F.mjs.map +0 -7
- package/dist/lib/neutral/chunk-KGV3QIRX.mjs.map +0 -7
- package/dist/lib/neutral/chunk-M2KVTHZM.mjs.map +0 -7
- package/dist/lib/neutral/chunk-MXQJZCPY.mjs.map +0 -7
- package/dist/lib/neutral/chunk-O3TZFQCT.mjs.map +0 -7
- package/dist/lib/neutral/chunk-OVUBTQLT.mjs.map +0 -7
- package/dist/lib/neutral/chunk-PP4DNUZU.mjs.map +0 -7
- package/dist/lib/neutral/chunk-QXF3LGN2.mjs.map +0 -7
- package/dist/lib/neutral/chunk-T4MPQJ7X.mjs.map +0 -7
- package/dist/lib/neutral/chunk-W7OP5HGZ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-ZTUBYOGB.mjs.map +0 -7
- package/dist/lib/neutral/chunk-ZWKJ4LZJ.mjs.map +0 -7
- package/dist/types/src/internal/annotations/annotations.d.ts.map +0 -1
- package/dist/types/src/internal/annotations/annotations.test.d.ts.map +0 -1
- package/dist/types/src/internal/annotations/index.d.ts +0 -3
- package/dist/types/src/internal/annotations/index.d.ts.map +0 -1
- package/dist/types/src/internal/annotations/util.d.ts.map +0 -1
- package/dist/types/src/internal/api/annotations.d.ts +0 -23
- package/dist/types/src/internal/api/annotations.d.ts.map +0 -1
- package/dist/types/src/internal/api/entity.d.ts.map +0 -1
- package/dist/types/src/internal/api/index.d.ts.map +0 -1
- package/dist/types/src/internal/api/meta.d.ts.map +0 -1
- package/dist/types/src/internal/api/sorting.d.ts.map +0 -1
- package/dist/types/src/internal/api/version.d.ts.map +0 -1
- package/dist/types/src/internal/entities/entity.d.ts.map +0 -1
- package/dist/types/src/internal/entities/index.d.ts.map +0 -1
- package/dist/types/src/internal/entities/model.d.ts.map +0 -1
- package/dist/types/src/internal/entities/object.d.ts.map +0 -1
- package/dist/types/src/internal/entities/relation.d.ts.map +0 -1
- package/dist/types/src/internal/entities/util.d.ts.map +0 -1
- package/dist/types/src/internal/formats/date.d.ts.map +0 -1
- package/dist/types/src/internal/formats/date.test.d.ts.map +0 -1
- package/dist/types/src/internal/formats/format.d.ts.map +0 -1
- package/dist/types/src/internal/formats/format.test.d.ts.map +0 -1
- package/dist/types/src/internal/formats/index.d.ts.map +0 -1
- package/dist/types/src/internal/formats/number.d.ts.map +0 -1
- package/dist/types/src/internal/formats/object.d.ts.map +0 -1
- package/dist/types/src/internal/formats/select.d.ts.map +0 -1
- package/dist/types/src/internal/formats/string.d.ts.map +0 -1
- package/dist/types/src/internal/formats/types.d.ts.map +0 -1
- package/dist/types/src/internal/json-schema/annotations.d.ts.map +0 -1
- package/dist/types/src/internal/json-schema/effect-schema.test.d.ts.map +0 -1
- package/dist/types/src/internal/json-schema/index.d.ts.map +0 -1
- package/dist/types/src/internal/json-schema/json-schema-normalize.d.ts.map +0 -1
- package/dist/types/src/internal/json-schema/json-schema-type.d.ts.map +0 -1
- package/dist/types/src/internal/json-schema/json-schema.d.ts.map +0 -1
- package/dist/types/src/internal/json-schema/json-schema.test.d.ts.map +0 -1
- package/dist/types/src/internal/object/clone.d.ts.map +0 -1
- package/dist/types/src/internal/object/common.d.ts.map +0 -1
- package/dist/types/src/internal/object/create-object.d.ts.map +0 -1
- package/dist/types/src/internal/object/create-object.test.d.ts.map +0 -1
- package/dist/types/src/internal/object/deleted.d.ts.map +0 -1
- package/dist/types/src/internal/object/ids.d.ts.map +0 -1
- package/dist/types/src/internal/object/index.d.ts.map +0 -1
- package/dist/types/src/internal/object/inspect.d.ts.map +0 -1
- package/dist/types/src/internal/object/json-serializer.d.ts.map +0 -1
- package/dist/types/src/internal/object/json-serializer.test.d.ts.map +0 -1
- package/dist/types/src/internal/object/schema-validator.d.ts +0 -2
- package/dist/types/src/internal/object/schema-validator.d.ts.map +0 -1
- package/dist/types/src/internal/object/schema-validator.test.d.ts.map +0 -1
- package/dist/types/src/internal/object/set-value.d.ts.map +0 -1
- package/dist/types/src/internal/object/set-value.test.d.ts.map +0 -1
- package/dist/types/src/internal/object/snapshot.d.ts.map +0 -1
- package/dist/types/src/internal/object/typed-object.d.ts.map +0 -1
- package/dist/types/src/internal/object/typed-object.test.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/change-context.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/change.test.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/define-hidden-property.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/errors.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/event-batch.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/handler.test.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/index.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/json-serializer.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/make-object.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/ownership.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/proxy-types.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/proxy-utils.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/reactive-array.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/schema-validator.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/schema.test.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/symbols.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/typed-handler.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/typed-handler.test.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/typed-object.test.d.ts.map +0 -1
- package/dist/types/src/internal/ref/index.d.ts.map +0 -1
- package/dist/types/src/internal/ref/ref-array.d.ts.map +0 -1
- package/dist/types/src/internal/ref/ref.d.ts.map +0 -1
- package/dist/types/src/internal/ref/ref.test.d.ts.map +0 -1
- package/dist/types/src/internal/schema/compose.d.ts.map +0 -1
- package/dist/types/src/internal/schema/compose.test.d.ts.map +0 -1
- package/dist/types/src/internal/schema/echo-schema.d.ts.map +0 -1
- package/dist/types/src/internal/schema/index.d.ts.map +0 -1
- package/dist/types/src/internal/schema/manipulation.d.ts.map +0 -1
- package/dist/types/src/internal/schema/persistent-schema.d.ts.map +0 -1
- package/dist/types/src/internal/types/base.d.ts.map +0 -1
- package/dist/types/src/internal/types/entity.d.ts.map +0 -1
- package/dist/types/src/internal/types/index.d.ts.map +0 -1
- package/dist/types/src/internal/types/meta.d.ts.map +0 -1
- package/dist/types/src/internal/types/typename.d.ts.map +0 -1
- package/dist/types/src/internal/types/version.d.ts.map +0 -1
- package/src/internal/api/annotations.ts +0 -60
- /package/dist/lib/neutral/{chunk-ANHVGJI4.mjs.map → chunk-7RVZT53K.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-OMUPQMLR.mjs.map → chunk-V72DY6LU.mjs.map} +0 -0
- /package/dist/types/src/internal/{annotations → Annotation}/annotations.test.d.ts +0 -0
- /package/dist/types/src/internal/{entities → Entity}/util.d.ts +0 -0
- /package/dist/types/src/internal/{formats → Format}/date.d.ts +0 -0
- /package/dist/types/src/internal/{formats → Format}/date.test.d.ts +0 -0
- /package/dist/types/src/internal/{formats → Format}/format.d.ts +0 -0
- /package/dist/types/src/internal/{formats → Format}/format.test.d.ts +0 -0
- /package/dist/types/src/internal/{formats → Format}/index.d.ts +0 -0
- /package/dist/types/src/internal/{formats → Format}/number.d.ts +0 -0
- /package/dist/types/src/internal/{formats → Format}/object.d.ts +0 -0
- /package/dist/types/src/internal/{formats → Format}/select.d.ts +0 -0
- /package/dist/types/src/internal/{formats → Format}/string.d.ts +0 -0
- /package/dist/types/src/internal/{json-schema → JsonSchema}/effect-schema.test.d.ts +0 -0
- /package/dist/types/src/internal/{json-schema → JsonSchema}/index.d.ts +0 -0
- /package/dist/types/src/internal/{json-schema → JsonSchema}/json-schema-normalize.d.ts +0 -0
- /package/dist/types/src/internal/{json-schema → JsonSchema}/json-schema.test.d.ts +0 -0
- /package/dist/types/src/internal/{object → Obj}/clone.d.ts +0 -0
- /package/dist/types/src/internal/{object → Obj}/common.d.ts +0 -0
- /package/dist/types/src/internal/{object → Obj}/create-object.test.d.ts +0 -0
- /package/dist/types/src/internal/{object → Obj}/ids.d.ts +0 -0
- /package/dist/types/src/internal/{object → Obj}/index.d.ts +0 -0
- /package/dist/types/src/internal/{object → Obj}/inspect.d.ts +0 -0
- /package/dist/types/src/internal/{object → Obj}/json-serializer.test.d.ts +0 -0
- /package/dist/types/src/internal/{object → Obj}/schema-validator.test.d.ts +0 -0
- /package/dist/types/src/internal/{object → Obj}/set-value.test.d.ts +0 -0
- /package/dist/types/src/internal/{object → Obj}/snapshot.d.ts +0 -0
- /package/dist/types/src/internal/{object → Obj}/typed-object.test.d.ts +0 -0
- /package/dist/types/src/internal/{ref → Ref}/index.d.ts +0 -0
- /package/dist/types/src/internal/{ref → Ref}/ref.test.d.ts +0 -0
- /package/dist/types/src/internal/{schema → Type}/compose.test.d.ts +0 -0
- /package/dist/types/src/internal/{schema → Type}/index.d.ts +0 -0
- /package/dist/types/src/internal/{schema → Type}/manipulation.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/change.test.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/define-hidden-property.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/event-batch.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/handler.test.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/index.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/json-serializer.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/make-object.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/ownership.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/proxy-types.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/proxy-utils.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/schema-validator.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/schema.test.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/symbols.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/typed-handler.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/typed-handler.test.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/typed-object.test.d.ts +0 -0
- /package/dist/types/src/internal/{types → common/types}/base.d.ts +0 -0
- /package/dist/types/src/internal/{types → common/types}/typename.d.ts +0 -0
- /package/src/internal/{entities → Entity}/util.ts +0 -0
- /package/src/internal/{formats → Format}/date.ts +0 -0
- /package/src/internal/{formats → Format}/format.ts +0 -0
- /package/src/internal/{formats → Format}/index.ts +0 -0
- /package/src/internal/{formats → Format}/number.ts +0 -0
- /package/src/internal/{formats → Format}/object.ts +0 -0
- /package/src/internal/{formats → Format}/select.ts +0 -0
- /package/src/internal/{formats → Format}/string.ts +0 -0
- /package/src/internal/{json-schema → JsonSchema}/effect-schema.test.ts +0 -0
- /package/src/internal/{json-schema → JsonSchema}/index.ts +0 -0
- /package/src/internal/{json-schema → JsonSchema}/json-schema-normalize.ts +0 -0
- /package/src/internal/{object → Obj}/ids.ts +0 -0
- /package/src/internal/{object → Obj}/index.ts +0 -0
- /package/src/internal/{object → Obj}/schema-validator.test.ts +0 -0
- /package/src/internal/{ref → Ref}/index.ts +0 -0
- /package/src/internal/{schema → Type}/index.ts +0 -0
- /package/src/internal/{proxy → common/proxy}/define-hidden-property.ts +0 -0
- /package/src/internal/{proxy → common/proxy}/event-batch.ts +0 -0
- /package/src/internal/{proxy → common/proxy}/index.ts +0 -0
- /package/src/internal/{proxy → common/proxy}/proxy-types.ts +0 -0
- /package/src/internal/{proxy → common/proxy}/proxy-utils.ts +0 -0
- /package/src/internal/{proxy → common/proxy}/schema-validator.ts +0 -0
- /package/src/internal/{proxy → common/proxy}/symbols.ts +0 -0
- /package/src/internal/{types → common/types}/base.ts +0 -0
- /package/src/internal/{types → common/types}/typename.ts +0 -0
- /package/src/internal/{types → common/types}/version.ts +0 -0
package/src/Json.test.ts
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { DXN, ObjectId } from '@dxos/keys';
|
|
8
|
+
import { safeStringify } from '@dxos/util';
|
|
9
|
+
|
|
10
|
+
import * as Database from './Database';
|
|
11
|
+
import * as Json from './Json';
|
|
12
|
+
|
|
13
|
+
/** Mint a random ECHO object id usable as both a stub-db key and a DXN payload. */
|
|
14
|
+
const newId = (): string => ObjectId.random();
|
|
15
|
+
|
|
16
|
+
/** Build a fake encoded ref for a local-space object id. */
|
|
17
|
+
const encodeRef = (id: string): { '/': string } => ({ '/': DXN.fromLocalObjectId(id).toString() });
|
|
18
|
+
|
|
19
|
+
/** Minimal stub: `createRefReplacer` only touches `db.getObjectById`. */
|
|
20
|
+
const makeStubDb = (objects: Record<string, unknown>): Database.Database => {
|
|
21
|
+
return {
|
|
22
|
+
getObjectById: (id: string) => objects[id],
|
|
23
|
+
} as unknown as Database.Database;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Run a value through the replacer's public contract — `JSON.stringify(value, replacer)` —
|
|
28
|
+
* then re-parse the result so tests can assert on plain JS shapes. This mirrors the way
|
|
29
|
+
* the JSON highlighter invokes the replacer in production.
|
|
30
|
+
*/
|
|
31
|
+
const stringifyWith = (replacer: Json.JsonReplacer, value: unknown): unknown =>
|
|
32
|
+
JSON.parse(JSON.stringify(value, replacer));
|
|
33
|
+
|
|
34
|
+
describe('createRefReplacer', () => {
|
|
35
|
+
test('passes plain values through unchanged', () => {
|
|
36
|
+
const replacer = Json.createRefReplacer({ db: makeStubDb({}) });
|
|
37
|
+
const subject = { a: 1, b: 'two', c: [3, { d: 4 }] };
|
|
38
|
+
expect(stringifyWith(replacer, subject)).toEqual(subject);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('inlines refs at default depth (1)', () => {
|
|
42
|
+
const id = newId();
|
|
43
|
+
const target = { name: 'inlined' };
|
|
44
|
+
const replacer = Json.createRefReplacer({ db: makeStubDb({ [id]: target }) });
|
|
45
|
+
const subject = { ref: encodeRef(id) };
|
|
46
|
+
expect(stringifyWith(replacer, subject)).toEqual({ ref: target });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('does not follow refs when depth is 0', () => {
|
|
50
|
+
const id = newId();
|
|
51
|
+
const target = { name: 'inlined' };
|
|
52
|
+
const ref = encodeRef(id);
|
|
53
|
+
const replacer = Json.createRefReplacer({ db: makeStubDb({ [id]: target }), depth: 0 });
|
|
54
|
+
expect(stringifyWith(replacer, { ref })).toEqual({ ref });
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('inlines refs across multiple levels up to depth', () => {
|
|
58
|
+
const innerId = newId();
|
|
59
|
+
const middleId = newId();
|
|
60
|
+
const inner = { name: 'inner' };
|
|
61
|
+
const middle = { ref: encodeRef(innerId) };
|
|
62
|
+
const outer = { ref: encodeRef(middleId) };
|
|
63
|
+
const db = makeStubDb({ [innerId]: inner, [middleId]: middle });
|
|
64
|
+
|
|
65
|
+
expect(stringifyWith(Json.createRefReplacer({ db, depth: 1 }), outer)).toEqual({
|
|
66
|
+
ref: { ref: encodeRef(innerId) },
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
expect(stringifyWith(Json.createRefReplacer({ db, depth: 2 }), outer)).toEqual({
|
|
70
|
+
ref: { ref: inner },
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('leaves refs encoded when the target is missing in the db', () => {
|
|
75
|
+
const ref = encodeRef(newId());
|
|
76
|
+
const replacer = Json.createRefReplacer({ db: makeStubDb({}) });
|
|
77
|
+
expect(stringifyWith(replacer, { ref })).toEqual({ ref });
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('leaves non-DXN single-key { "/": string } objects untouched', () => {
|
|
81
|
+
// Same `{ '/': string }` shape is used by other IPLD-style refs (e.g. CIDs); those should
|
|
82
|
+
// not crash the replacer and should pass through verbatim.
|
|
83
|
+
const cidLike = { '/': 'bafybeibwzifw7izxykxz' };
|
|
84
|
+
const replacer = Json.createRefReplacer({ db: makeStubDb({}) });
|
|
85
|
+
expect(stringifyWith(replacer, { ref: cidLike })).toEqual({ ref: cidLike });
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('leaves malformed dxn strings untouched', () => {
|
|
89
|
+
const malformed = { '/': 'dxn:not-a-real-dxn' };
|
|
90
|
+
const replacer = Json.createRefReplacer({ db: makeStubDb({}) });
|
|
91
|
+
expect(stringifyWith(replacer, { ref: malformed })).toEqual({ ref: malformed });
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test('leaves non-echo dxns untouched (e.g. type DXN)', () => {
|
|
95
|
+
// Type DXNs share the `dxn:` prefix but `asEchoDXN()` returns undefined.
|
|
96
|
+
const typeRef = { '/': DXN.fromTypename('com.example.Thing').toString() };
|
|
97
|
+
const replacer = Json.createRefReplacer({ db: makeStubDb({}) });
|
|
98
|
+
expect(stringifyWith(replacer, { ref: typeRef })).toEqual({ ref: typeRef });
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('inlines refs inside arrays', () => {
|
|
102
|
+
const idA = newId();
|
|
103
|
+
const idB = newId();
|
|
104
|
+
const a = { name: 'a' };
|
|
105
|
+
const b = { name: 'b' };
|
|
106
|
+
const replacer = Json.createRefReplacer({ db: makeStubDb({ [idA]: a, [idB]: b }) });
|
|
107
|
+
expect(stringifyWith(replacer, { items: [encodeRef(idA), encodeRef(idB), { plain: true }] })).toEqual({
|
|
108
|
+
items: [a, b, { plain: true }],
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test('walks nested objects recursively', () => {
|
|
113
|
+
const innerId = newId();
|
|
114
|
+
const inner = { name: 'inner' };
|
|
115
|
+
const replacer = Json.createRefReplacer({ db: makeStubDb({ [innerId]: inner }) });
|
|
116
|
+
const subject = { outer: { mid: { ref: encodeRef(innerId) } } };
|
|
117
|
+
expect(stringifyWith(replacer, subject)).toEqual({ outer: { mid: { ref: inner } } });
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('a single replacer invocation does not recurse on its own', () => {
|
|
121
|
+
// The replacer is per-call; JSON.stringify drives the tree walk. Calling the replacer
|
|
122
|
+
// directly on a cyclic input must therefore return without touching the cycle.
|
|
123
|
+
const replacer = Json.createRefReplacer({ db: makeStubDb({}) });
|
|
124
|
+
const node: any = { name: 'self' };
|
|
125
|
+
node.self = node;
|
|
126
|
+
|
|
127
|
+
expect(() => replacer('', node)).not.toThrow();
|
|
128
|
+
expect(replacer('', node)).toBe(node);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test('invokes `toJSON` on resolved targets so refs in the target are re-walked', () => {
|
|
132
|
+
// Simulates the ECHO-object branch: `db.getObjectById` returns a live proxy, the replacer
|
|
133
|
+
// calls `.toJSON()` to get the encoded form, then continues walking that form. A ref nested
|
|
134
|
+
// inside the target should be inlined when there's depth budget remaining.
|
|
135
|
+
const outerId = newId();
|
|
136
|
+
const innerId = newId();
|
|
137
|
+
const inner = { name: 'inner' };
|
|
138
|
+
const target = {
|
|
139
|
+
toJSON: () => ({ nestedRef: encodeRef(innerId) }),
|
|
140
|
+
};
|
|
141
|
+
const replacer = Json.createRefReplacer({ db: makeStubDb({ [outerId]: target, [innerId]: inner }), depth: 2 });
|
|
142
|
+
expect(stringifyWith(replacer, { ref: encodeRef(outerId) })).toEqual({
|
|
143
|
+
ref: { nestedRef: inner },
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test('depth budget counts ref hops, not tree depth — a ref deep in a plain tree still resolves', () => {
|
|
148
|
+
// A ref nested under arbitrarily many plain objects is one ref hop from the root, so
|
|
149
|
+
// `depth: 1` resolves it. `depth: 0` leaves it encoded.
|
|
150
|
+
const innerId = newId();
|
|
151
|
+
const inner = { name: 'inner' };
|
|
152
|
+
const subject = { a: { b: { c: { d: { ref: encodeRef(innerId) } } } } };
|
|
153
|
+
|
|
154
|
+
const inlining = Json.createRefReplacer({ db: makeStubDb({ [innerId]: inner }), depth: 1 });
|
|
155
|
+
expect(stringifyWith(inlining, subject)).toEqual({ a: { b: { c: { d: { ref: inner } } } } });
|
|
156
|
+
|
|
157
|
+
const passthrough = Json.createRefReplacer({ db: makeStubDb({ [innerId]: inner }), depth: 0 });
|
|
158
|
+
expect(stringifyWith(passthrough, subject)).toEqual(subject);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test('inlines refs when invoked through safeStringify (production path)', () => {
|
|
162
|
+
// `JsonHighlighter` runs the replacer through `@dxos/util/safeStringify`, whose inner
|
|
163
|
+
// wrapper short-circuits the root call without forwarding it to the user's filter. The
|
|
164
|
+
// replacer must therefore work on a per-call basis — not as a one-shot root tree walk.
|
|
165
|
+
// This regression-tests that integration: the `content` ref must inline.
|
|
166
|
+
const targetId = newId();
|
|
167
|
+
const target = { toJSON: () => ({ name: 'README content' }) };
|
|
168
|
+
const document = { id: '01ABC', name: 'README', content: encodeRef(targetId) };
|
|
169
|
+
|
|
170
|
+
const replacer = Json.createRefReplacer({ db: makeStubDb({ [targetId]: target }) });
|
|
171
|
+
const out = JSON.parse(safeStringify(document, replacer, 0)!);
|
|
172
|
+
|
|
173
|
+
expect(out).toEqual({ id: '01ABC', name: 'README', content: { name: 'README content' } });
|
|
174
|
+
});
|
|
175
|
+
});
|
package/src/Json.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { DXN } 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:')) {
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let echoId: string | undefined;
|
|
72
|
+
try {
|
|
73
|
+
echoId = DXN.parse(dxnString).asEchoDXN()?.echoId;
|
|
74
|
+
} catch {
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!echoId) {
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
const target = db.getObjectById(echoId);
|
|
82
|
+
if (!target) {
|
|
83
|
+
return value;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const encoded = toJson(target);
|
|
87
|
+
if (encoded != null && typeof encoded === 'object') {
|
|
88
|
+
// Children of the resolved target are one hop deeper.
|
|
89
|
+
hops.set(encoded as object, parentHops + 1);
|
|
90
|
+
}
|
|
91
|
+
return encoded;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Pass-through object: children inherit the parent's hop count (this branch doesn't burn
|
|
95
|
+
// budget).
|
|
96
|
+
if (value != null && typeof value === 'object') {
|
|
97
|
+
hops.set(value, parentHops);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return value;
|
|
101
|
+
};
|
|
102
|
+
};
|
package/src/JsonSchema.ts
CHANGED
|
@@ -2,23 +2,25 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
// @import-as-namespace
|
|
6
|
+
|
|
5
7
|
import type * as Schema from 'effect/Schema';
|
|
6
8
|
|
|
7
|
-
import * as
|
|
9
|
+
import * as jsonSchemaInternal from './internal/JsonSchema';
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
12
|
* Decode JSON Schema to Effect Schema.
|
|
11
13
|
*/
|
|
12
|
-
export const toEffectSchema =
|
|
14
|
+
export const toEffectSchema = jsonSchemaInternal.toEffectSchema;
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
* Encode Effect Schema to JSON Schema.
|
|
16
18
|
*/
|
|
17
|
-
export const toJsonSchema =
|
|
19
|
+
export const toJsonSchema = jsonSchemaInternal.toJsonSchema;
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* Serializable JsonSchema type definition.
|
|
21
23
|
*/
|
|
22
|
-
export type JsonSchema =
|
|
24
|
+
export type JsonSchema = jsonSchemaInternal.JsonSchemaType;
|
|
23
25
|
|
|
24
|
-
export const JsonSchema: Schema.Schema<
|
|
26
|
+
export const JsonSchema: Schema.Schema<jsonSchemaInternal.JsonSchemaType> = jsonSchemaInternal.JsonSchemaType;
|
package/src/Migration.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
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 DXN } from '@dxos/keys';
|
|
10
|
+
|
|
11
|
+
import type * as Database from './Database';
|
|
12
|
+
import type * as Entity from './Entity';
|
|
13
|
+
import { getSchemaDXN } from './internal';
|
|
14
|
+
|
|
15
|
+
type DefineObjectMigrationOptions<From extends Schema.Schema.AnyNoContext, To extends Schema.Schema.AnyNoContext> = {
|
|
16
|
+
from: From;
|
|
17
|
+
to: To;
|
|
18
|
+
/**
|
|
19
|
+
* Pure function that converts the old object data to the new object data.
|
|
20
|
+
*/
|
|
21
|
+
// TODO(dmaretskyi): `id` should not be a part of the schema.
|
|
22
|
+
transform: (
|
|
23
|
+
from: Schema.Schema.Type<From>,
|
|
24
|
+
context: ObjectMigrationContext,
|
|
25
|
+
) => Promise<Omit<Schema.Schema.Type<To>, 'id' | Entity.KindId>>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Callback that is called after the object is migrated. Called for every object that is migrated.
|
|
29
|
+
*
|
|
30
|
+
* NOTE: Database mutations performed in this callback are not guaranteed to be idempotent.
|
|
31
|
+
* If multiple peers run the migration separately, the effects may be applied multiple times.
|
|
32
|
+
*/
|
|
33
|
+
onMigration: (params: OnMigrateProps<From, To>) => Promise<void>;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Context passed to object migration callbacks.
|
|
38
|
+
*/
|
|
39
|
+
export type ObjectMigrationContext = {
|
|
40
|
+
db: Database.Database;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
type OnMigrateProps<From extends Schema.Schema.AnyNoContext, To extends Schema.Schema.AnyNoContext> = {
|
|
44
|
+
before: Schema.Schema.Type<From>;
|
|
45
|
+
object: Schema.Schema.Type<To>;
|
|
46
|
+
db: Database.Database;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Definition of a migration from one object schema version to another.
|
|
51
|
+
*/
|
|
52
|
+
export type ObjectMigration = {
|
|
53
|
+
fromType: DXN;
|
|
54
|
+
toType: DXN;
|
|
55
|
+
fromSchema: Schema.Schema.AnyNoContext;
|
|
56
|
+
toSchema: Schema.Schema.AnyNoContext;
|
|
57
|
+
transform: (from: unknown, context: ObjectMigrationContext) => Promise<unknown>;
|
|
58
|
+
onMigration: (params: OnMigrateProps<any, any>) => Promise<void>;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Define a migration between two object schemas.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* const migration = Migration.define({
|
|
67
|
+
* from: ContactV1,
|
|
68
|
+
* to: ContactV2,
|
|
69
|
+
* transform: async (from) => ({ name: `${from.firstName} ${from.lastName}` }),
|
|
70
|
+
* onMigration: async () => {},
|
|
71
|
+
* });
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export const define = <From extends Schema.Schema.AnyNoContext, To extends Schema.Schema.AnyNoContext>(
|
|
75
|
+
options: DefineObjectMigrationOptions<From, To>,
|
|
76
|
+
): ObjectMigration => {
|
|
77
|
+
const fromType = getSchemaDXN(options.from);
|
|
78
|
+
if (!fromType) {
|
|
79
|
+
throw new Error('Invalid from schema');
|
|
80
|
+
}
|
|
81
|
+
const toType = getSchemaDXN(options.to);
|
|
82
|
+
if (!toType) {
|
|
83
|
+
throw new Error('Invalid to schema');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
fromType,
|
|
88
|
+
toType,
|
|
89
|
+
fromSchema: options.from,
|
|
90
|
+
toSchema: options.to,
|
|
91
|
+
transform: options.transform as any,
|
|
92
|
+
onMigration: options.onMigration as any,
|
|
93
|
+
};
|
|
94
|
+
};
|
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';
|
|
@@ -46,8 +46,8 @@ describe('Obj', () => {
|
|
|
46
46
|
expect(Obj.getDXN(snapshot)).toBeDefined();
|
|
47
47
|
|
|
48
48
|
// getTypename - works with both.
|
|
49
|
-
expect(Obj.getTypename(obj)).toBe('example.
|
|
50
|
-
expect(Obj.getTypename(snapshot)).toBe('example.
|
|
49
|
+
expect(Obj.getTypename(obj)).toBe('com.example.type.person');
|
|
50
|
+
expect(Obj.getTypename(snapshot)).toBe('com.example.type.person');
|
|
51
51
|
|
|
52
52
|
// getMeta - works with both.
|
|
53
53
|
expect(Obj.getMeta(obj)).toBeDefined();
|
|
@@ -117,8 +117,8 @@ describe('Obj', () => {
|
|
|
117
117
|
|
|
118
118
|
test('returns keys from reactive object and snapshot', ({ expect }) => {
|
|
119
119
|
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
120
|
-
Obj.
|
|
121
|
-
const meta = Obj.getMeta(
|
|
120
|
+
Obj.update(obj, (obj) => {
|
|
121
|
+
const meta = Obj.getMeta(obj);
|
|
122
122
|
meta.keys.push({ source: SOURCE, id: 'key-1' });
|
|
123
123
|
meta.keys.push({ source: SOURCE, id: 'key-2' });
|
|
124
124
|
meta.keys.push({ source: 'other', id: 'key-3' });
|
|
@@ -166,8 +166,8 @@ describe('Obj', () => {
|
|
|
166
166
|
|
|
167
167
|
const cloned = Obj.clone(original);
|
|
168
168
|
|
|
169
|
-
Obj.
|
|
170
|
-
|
|
169
|
+
Obj.update(original, (original) => {
|
|
170
|
+
original.name = 'Bob';
|
|
171
171
|
});
|
|
172
172
|
|
|
173
173
|
expect(original.name).toBe('Bob');
|
|
@@ -206,8 +206,8 @@ describe('Obj', () => {
|
|
|
206
206
|
expect(cloned.employer?.target).toBe(person.employer?.target);
|
|
207
207
|
|
|
208
208
|
// Modifying the referenced object affects both
|
|
209
|
-
Obj.
|
|
210
|
-
|
|
209
|
+
Obj.update(employer, (employer) => {
|
|
210
|
+
employer.name = 'Updated DXOS';
|
|
211
211
|
});
|
|
212
212
|
|
|
213
213
|
expect(cloned.employer?.target?.name).toBe('Updated DXOS');
|
|
@@ -234,8 +234,8 @@ describe('Obj', () => {
|
|
|
234
234
|
expect(cloned.employer?.target?.name).toBe(employer.name);
|
|
235
235
|
|
|
236
236
|
// Modifying the original referenced object does not affect the clone
|
|
237
|
-
Obj.
|
|
238
|
-
|
|
237
|
+
Obj.update(employer, (employer) => {
|
|
238
|
+
employer.name = 'Updated DXOS';
|
|
239
239
|
});
|
|
240
240
|
|
|
241
241
|
expect(cloned.employer?.target?.name).toBe('DXOS');
|
|
@@ -333,8 +333,8 @@ describe('Obj', () => {
|
|
|
333
333
|
expect(cloned.address?.coordinates.lng).toBe(-122.4194);
|
|
334
334
|
|
|
335
335
|
// Modifying nested properties should be independent
|
|
336
|
-
Obj.
|
|
337
|
-
|
|
336
|
+
Obj.update(person, (person) => {
|
|
337
|
+
person.address!.city = 'New York';
|
|
338
338
|
});
|
|
339
339
|
|
|
340
340
|
expect(cloned.address?.city).toBe('San Francisco');
|
|
@@ -366,8 +366,8 @@ describe('Obj', () => {
|
|
|
366
366
|
expect(cloned.tasks?.[2]?.target).not.toBe(task3);
|
|
367
367
|
|
|
368
368
|
// Modifying original tasks should not affect cloned ones
|
|
369
|
-
Obj.
|
|
370
|
-
|
|
369
|
+
Obj.update(task1, (task1) => {
|
|
370
|
+
task1.title = 'Updated Task 1';
|
|
371
371
|
});
|
|
372
372
|
|
|
373
373
|
expect(cloned.tasks?.[0]?.target?.title).toBe('Task 1');
|
|
@@ -444,4 +444,96 @@ describe('Obj', () => {
|
|
|
444
444
|
expectTypeOf<Obj.Any>().toMatchTypeOf<Obj.Unknown>();
|
|
445
445
|
});
|
|
446
446
|
});
|
|
447
|
+
|
|
448
|
+
describe('Obj.updateFrom', () => {
|
|
449
|
+
test('returns false when values already match', () => {
|
|
450
|
+
const target = Obj.make(TestSchema.Organization, { name: 'Acme', properties: { region: 'EU' } });
|
|
451
|
+
const source = Obj.make(TestSchema.Organization, { name: 'Acme', properties: { region: 'EU' } });
|
|
452
|
+
Obj.update(target, (target) => {
|
|
453
|
+
expect(Obj.updateFrom(target, source)).toBe(false);
|
|
454
|
+
});
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
test('updates scalar and nested record fields on Organization', () => {
|
|
458
|
+
const target = Obj.make(TestSchema.Organization, {
|
|
459
|
+
name: 'Old',
|
|
460
|
+
properties: { a: '1' },
|
|
461
|
+
});
|
|
462
|
+
const source = Obj.make(TestSchema.Organization, {
|
|
463
|
+
name: 'New',
|
|
464
|
+
properties: { a: '2', b: '3' },
|
|
465
|
+
});
|
|
466
|
+
Obj.update(target, (target) => {
|
|
467
|
+
expect(Obj.updateFrom(target, source)).toBe(true);
|
|
468
|
+
});
|
|
469
|
+
expect(target.name).toBe('New');
|
|
470
|
+
expect(target.properties).toEqual({ a: '2', b: '3' });
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
test('compares employer refs by DXN and updates Person fields', () => {
|
|
474
|
+
const orgA = Obj.make(TestSchema.Organization, { name: 'A' });
|
|
475
|
+
const orgB = Obj.make(TestSchema.Organization, { name: 'B' });
|
|
476
|
+
const target = Obj.make(TestSchema.Person, {
|
|
477
|
+
name: 'Ann',
|
|
478
|
+
username: 'ann',
|
|
479
|
+
email: 'ann@x.test',
|
|
480
|
+
employer: Ref.make(orgA),
|
|
481
|
+
address: { city: 'X', state: 'Y', zip: '1', coordinates: { lat: 0, lng: 0 } },
|
|
482
|
+
});
|
|
483
|
+
const source = Obj.make(TestSchema.Person, {
|
|
484
|
+
name: 'Ann',
|
|
485
|
+
username: 'ann',
|
|
486
|
+
email: 'ann@x.test',
|
|
487
|
+
employer: Ref.make(orgB),
|
|
488
|
+
address: { city: 'Portland', state: 'OR', zip: '97201', coordinates: { lat: 45.5, lng: -122.6 } },
|
|
489
|
+
});
|
|
490
|
+
Obj.update(target, (target) => {
|
|
491
|
+
expect(Obj.updateFrom(target, source)).toBe(true);
|
|
492
|
+
});
|
|
493
|
+
expect(target.employer?.dxn.toString()).toBe(Ref.make(orgB).dxn.toString());
|
|
494
|
+
expect(target.address?.city).toBe('Portland');
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
test('updates array of task refs when DXNs differ', () => {
|
|
498
|
+
const t1 = Obj.make(TestSchema.Task, { title: 'One' });
|
|
499
|
+
const t2 = Obj.make(TestSchema.Task, { title: 'Two' });
|
|
500
|
+
const t3 = Obj.make(TestSchema.Task, { title: 'Three' });
|
|
501
|
+
const target = Obj.make(TestSchema.Person, {
|
|
502
|
+
name: 'Bob',
|
|
503
|
+
username: 'bob',
|
|
504
|
+
email: 'bob@x.test',
|
|
505
|
+
tasks: [Ref.make(t1), Ref.make(t2)],
|
|
506
|
+
});
|
|
507
|
+
const source = Obj.make(TestSchema.Person, {
|
|
508
|
+
name: 'Bob',
|
|
509
|
+
username: 'bob',
|
|
510
|
+
email: 'bob@x.test',
|
|
511
|
+
tasks: [Ref.make(t1), Ref.make(t3)],
|
|
512
|
+
});
|
|
513
|
+
Obj.update(target, (target) => {
|
|
514
|
+
expect(Obj.updateFrom(target, source)).toBe(true);
|
|
515
|
+
});
|
|
516
|
+
expect(target.tasks?.map((r) => r.dxn.toString())).toEqual(source.tasks?.map((r) => r.dxn.toString()));
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
test('respects include option', () => {
|
|
520
|
+
const target = Obj.make(TestSchema.Organization, { name: 'Keep', properties: { x: '1' } });
|
|
521
|
+
const source = Obj.make(TestSchema.Organization, { name: 'Drop', properties: { x: '2' } });
|
|
522
|
+
Obj.update(target, (target) => {
|
|
523
|
+
expect(Obj.updateFrom(target, source, { include: ['properties'] })).toBe(true);
|
|
524
|
+
});
|
|
525
|
+
expect(target.name).toBe('Keep');
|
|
526
|
+
expect(target.properties).toEqual({ x: '2' });
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
test('respects exclude option', () => {
|
|
530
|
+
const target = Obj.make(TestSchema.Organization, { name: 'Old', properties: { x: '1' } });
|
|
531
|
+
const source = Obj.make(TestSchema.Organization, { name: 'New', properties: { x: '2' } });
|
|
532
|
+
Obj.update(target, (target) => {
|
|
533
|
+
expect(Obj.updateFrom(target, source, { exclude: ['name'] })).toBe(true);
|
|
534
|
+
});
|
|
535
|
+
expect(target.name).toBe('Old');
|
|
536
|
+
expect(target.properties).toEqual({ x: '2' });
|
|
537
|
+
});
|
|
538
|
+
});
|
|
447
539
|
});
|