@dxos/echo 0.8.4-main.406dc2a → 0.8.4-main.59c2e9b
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/README.md +1 -2
- package/dist/lib/browser/Annotation.mjs +33 -0
- package/dist/lib/browser/Database.mjs +18 -0
- package/dist/lib/browser/Entity.mjs +52 -0
- package/dist/lib/browser/Entity.mjs.map +7 -0
- package/dist/lib/browser/Err.mjs +11 -0
- package/dist/lib/browser/Err.mjs.map +7 -0
- package/dist/lib/browser/Filter.mjs +62 -0
- package/dist/lib/browser/Filter.mjs.map +7 -0
- package/dist/lib/browser/Format.mjs +67 -0
- package/dist/lib/browser/Format.mjs.map +7 -0
- package/dist/lib/browser/JsonSchema.mjs +20 -0
- package/dist/lib/browser/JsonSchema.mjs.map +7 -0
- package/dist/lib/browser/Key.mjs +13 -0
- package/dist/lib/browser/Key.mjs.map +7 -0
- package/dist/lib/browser/Obj.mjs +91 -0
- package/dist/lib/browser/Obj.mjs.map +7 -0
- package/dist/lib/browser/Order.mjs +13 -0
- package/dist/lib/browser/Order.mjs.map +7 -0
- package/dist/lib/browser/Query.mjs +27 -0
- package/dist/lib/browser/Query.mjs.map +7 -0
- package/dist/lib/browser/QueryResult.mjs +3 -0
- package/dist/lib/browser/QueryResult.mjs.map +7 -0
- package/dist/lib/browser/Ref.mjs +23 -0
- package/dist/lib/browser/Ref.mjs.map +7 -0
- package/dist/lib/browser/Relation.mjs +85 -0
- package/dist/lib/browser/Relation.mjs.map +7 -0
- package/dist/lib/browser/SchemaRegistry.mjs +3 -0
- package/dist/lib/browser/SchemaRegistry.mjs.map +7 -0
- package/dist/lib/browser/Tag.mjs +26 -0
- package/dist/lib/browser/Tag.mjs.map +7 -0
- package/dist/lib/browser/Type.mjs +48 -0
- package/dist/lib/browser/Type.mjs.map +7 -0
- package/dist/lib/browser/chunk-22JMFST2.mjs +24 -0
- package/dist/lib/browser/chunk-22JMFST2.mjs.map +7 -0
- package/dist/lib/browser/chunk-2SBB7OWV.mjs +250 -0
- package/dist/lib/browser/chunk-2SBB7OWV.mjs.map +7 -0
- package/dist/lib/browser/chunk-6L5HHUVU.mjs +158 -0
- package/dist/lib/browser/chunk-6L5HHUVU.mjs.map +7 -0
- package/dist/lib/browser/chunk-7STIBCP7.mjs +133 -0
- package/dist/lib/browser/chunk-7STIBCP7.mjs.map +7 -0
- package/dist/lib/browser/chunk-BJPE6CIC.mjs +3847 -0
- package/dist/lib/browser/chunk-BJPE6CIC.mjs.map +7 -0
- package/dist/lib/browser/chunk-CGS2ULMK.mjs +11 -0
- package/dist/lib/browser/chunk-CGS2ULMK.mjs.map +7 -0
- package/dist/lib/browser/chunk-CJ5YELTO.mjs +39 -0
- package/dist/lib/browser/chunk-CJ5YELTO.mjs.map +7 -0
- package/dist/lib/browser/chunk-FPOISFQK.mjs +40 -0
- package/dist/lib/browser/chunk-FPOISFQK.mjs.map +7 -0
- package/dist/lib/browser/chunk-FRDT7RA4.mjs +403 -0
- package/dist/lib/browser/chunk-FRDT7RA4.mjs.map +7 -0
- package/dist/lib/browser/chunk-INHXFXY5.mjs +22 -0
- package/dist/lib/browser/chunk-INHXFXY5.mjs.map +7 -0
- package/dist/lib/browser/chunk-IXVWLTG7.mjs +9 -0
- package/dist/lib/browser/chunk-IXVWLTG7.mjs.map +7 -0
- package/dist/lib/browser/chunk-JMKVF2YQ.mjs +43 -0
- package/dist/lib/browser/chunk-JMKVF2YQ.mjs.map +7 -0
- package/dist/lib/browser/chunk-KQQGVHFN.mjs +143 -0
- package/dist/lib/browser/chunk-KQQGVHFN.mjs.map +7 -0
- package/dist/lib/browser/chunk-MYCCGG2T.mjs +15 -0
- package/dist/lib/browser/chunk-MYCCGG2T.mjs.map +7 -0
- package/dist/lib/browser/chunk-NOPVNWPT.mjs +204 -0
- package/dist/lib/browser/chunk-NOPVNWPT.mjs.map +7 -0
- package/dist/lib/browser/chunk-PQZW3S6L.mjs +74 -0
- package/dist/lib/browser/chunk-PQZW3S6L.mjs.map +7 -0
- package/dist/lib/browser/chunk-RK4Z4JUZ.mjs +283 -0
- package/dist/lib/browser/chunk-RK4Z4JUZ.mjs.map +7 -0
- package/dist/lib/browser/chunk-U2J7TA7K.mjs +57 -0
- package/dist/lib/browser/chunk-U2J7TA7K.mjs.map +7 -0
- package/dist/lib/browser/chunk-W5D2GWAW.mjs +98 -0
- package/dist/lib/browser/chunk-W5D2GWAW.mjs.map +7 -0
- package/dist/lib/browser/chunk-XDIUHAAX.mjs +41 -0
- package/dist/lib/browser/chunk-XDIUHAAX.mjs.map +7 -0
- package/dist/lib/browser/chunk-YKTSSMDS.mjs +69 -0
- package/dist/lib/browser/chunk-YKTSSMDS.mjs.map +7 -0
- package/dist/lib/browser/chunk-ZAGAOZVY.mjs +288 -0
- package/dist/lib/browser/chunk-ZAGAOZVY.mjs.map +7 -0
- package/dist/lib/browser/chunk-ZHXZGIXD.mjs +9 -0
- package/dist/lib/browser/chunk-ZHXZGIXD.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +72 -22
- package/dist/lib/browser/internal/index.mjs +245 -120
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +295 -226
- package/dist/lib/browser/testing/index.mjs.map +4 -4
- package/dist/lib/node-esm/Annotation.mjs +33 -0
- package/dist/lib/node-esm/Annotation.mjs.map +7 -0
- package/dist/lib/node-esm/Database.mjs +18 -0
- package/dist/lib/node-esm/Database.mjs.map +7 -0
- package/dist/lib/node-esm/Entity.mjs +52 -0
- package/dist/lib/node-esm/Entity.mjs.map +7 -0
- package/dist/lib/node-esm/Err.mjs +11 -0
- package/dist/lib/node-esm/Err.mjs.map +7 -0
- package/dist/lib/node-esm/Filter.mjs +62 -0
- package/dist/lib/node-esm/Filter.mjs.map +7 -0
- package/dist/lib/node-esm/Format.mjs +67 -0
- package/dist/lib/node-esm/Format.mjs.map +7 -0
- package/dist/lib/node-esm/JsonSchema.mjs +20 -0
- package/dist/lib/node-esm/JsonSchema.mjs.map +7 -0
- package/dist/lib/node-esm/Key.mjs +13 -0
- package/dist/lib/node-esm/Key.mjs.map +7 -0
- package/dist/lib/node-esm/Obj.mjs +91 -0
- package/dist/lib/node-esm/Obj.mjs.map +7 -0
- package/dist/lib/node-esm/Order.mjs +13 -0
- package/dist/lib/node-esm/Order.mjs.map +7 -0
- package/dist/lib/node-esm/Query.mjs +27 -0
- package/dist/lib/node-esm/Query.mjs.map +7 -0
- package/dist/lib/node-esm/QueryResult.mjs +3 -0
- package/dist/lib/node-esm/QueryResult.mjs.map +7 -0
- package/dist/lib/node-esm/Ref.mjs +23 -0
- package/dist/lib/node-esm/Ref.mjs.map +7 -0
- package/dist/lib/node-esm/Relation.mjs +85 -0
- package/dist/lib/node-esm/Relation.mjs.map +7 -0
- package/dist/lib/node-esm/SchemaRegistry.mjs +3 -0
- package/dist/lib/node-esm/SchemaRegistry.mjs.map +7 -0
- package/dist/lib/node-esm/Tag.mjs +26 -0
- package/dist/lib/node-esm/Tag.mjs.map +7 -0
- package/dist/lib/node-esm/Type.mjs +48 -0
- package/dist/lib/node-esm/Type.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-4PNXQA64.mjs +250 -0
- package/dist/lib/node-esm/chunk-4PNXQA64.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-5OBN7GZW.mjs +158 -0
- package/dist/lib/node-esm/chunk-5OBN7GZW.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-AJEMYSIR.mjs +22 -0
- package/dist/lib/node-esm/chunk-AJEMYSIR.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-ANLVLWME.mjs +98 -0
- package/dist/lib/node-esm/chunk-ANLVLWME.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-DMR7OAFK.mjs +57 -0
- package/dist/lib/node-esm/chunk-DMR7OAFK.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-FWTSPIFF.mjs +133 -0
- package/dist/lib/node-esm/chunk-FWTSPIFF.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-ILMLLM4R.mjs +204 -0
- package/dist/lib/node-esm/chunk-ILMLLM4R.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-K37NA7PO.mjs +43 -0
- package/dist/lib/node-esm/chunk-K37NA7PO.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-LT3H4JOX.mjs +3847 -0
- package/dist/lib/node-esm/chunk-LT3H4JOX.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-MOLNWFNL.mjs +9 -0
- package/dist/lib/node-esm/chunk-MOLNWFNL.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-MOWUEW5P.mjs +15 -0
- package/dist/lib/node-esm/chunk-MOWUEW5P.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-NBWL7UCZ.mjs +40 -0
- package/dist/lib/node-esm/chunk-NBWL7UCZ.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-NRN3ZW2T.mjs +143 -0
- package/dist/lib/node-esm/chunk-NRN3ZW2T.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-QLI2EIJ2.mjs +41 -0
- package/dist/lib/node-esm/chunk-QLI2EIJ2.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-QYR67VBV.mjs +288 -0
- package/dist/lib/node-esm/chunk-QYR67VBV.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-UKGVOINP.mjs +9 -0
- package/dist/lib/node-esm/chunk-UKGVOINP.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-W6QIEBTQ.mjs +403 -0
- package/dist/lib/node-esm/chunk-W6QIEBTQ.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-XHJRMQZD.mjs +69 -0
- package/dist/lib/node-esm/chunk-XHJRMQZD.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-Y75VU7LB.mjs +74 -0
- package/dist/lib/node-esm/chunk-Y75VU7LB.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-YOLH5KS4.mjs +283 -0
- package/dist/lib/node-esm/chunk-YOLH5KS4.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-YQ2NWGL5.mjs +39 -0
- package/dist/lib/node-esm/chunk-YQ2NWGL5.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-ZBB67AKD.mjs +24 -0
- package/dist/lib/node-esm/chunk-ZBB67AKD.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +72 -22
- package/dist/lib/node-esm/internal/index.mjs +245 -120
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +295 -226
- package/dist/lib/node-esm/testing/index.mjs.map +4 -4
- package/dist/types/src/Annotation.d.ts +2 -0
- package/dist/types/src/Annotation.d.ts.map +1 -0
- package/dist/types/src/Database.d.ts +194 -0
- package/dist/types/src/Database.d.ts.map +1 -0
- package/dist/types/src/Entity.d.ts +142 -0
- package/dist/types/src/Entity.d.ts.map +1 -0
- package/dist/types/src/Entity.test.d.ts +2 -0
- package/dist/types/src/Entity.test.d.ts.map +1 -0
- package/dist/types/src/{errors.d.ts → Err.d.ts} +23 -31
- package/dist/types/src/Err.d.ts.map +1 -0
- package/dist/types/src/Filter.d.ts +120 -0
- package/dist/types/src/Filter.d.ts.map +1 -0
- package/dist/types/src/Format.d.ts +4 -0
- package/dist/types/src/Format.d.ts.map +1 -0
- package/dist/types/src/Hypergraph.d.ts +60 -0
- package/dist/types/src/Hypergraph.d.ts.map +1 -0
- package/dist/types/src/JsonSchema.d.ts +9 -0
- package/dist/types/src/JsonSchema.d.ts.map +1 -0
- package/dist/types/src/Key.d.ts +1 -0
- package/dist/types/src/Key.d.ts.map +1 -1
- package/dist/types/src/Obj.d.ts +302 -99
- package/dist/types/src/Obj.d.ts.map +1 -1
- package/dist/types/src/Obj.test.d.ts +2 -0
- package/dist/types/src/Obj.test.d.ts.map +1 -0
- package/dist/types/src/Order.d.ts +16 -0
- package/dist/types/src/Order.d.ts.map +1 -0
- package/dist/types/src/Query.d.ts +115 -0
- package/dist/types/src/Query.d.ts.map +1 -0
- package/dist/types/src/Query.test.d.ts +2 -0
- package/dist/types/src/Query.test.d.ts.map +1 -0
- package/dist/types/src/QueryResult.d.ts +80 -0
- package/dist/types/src/QueryResult.d.ts.map +1 -0
- package/dist/types/src/Ref.d.ts +13 -11
- package/dist/types/src/Ref.d.ts.map +1 -1
- package/dist/types/src/Relation.d.ts +242 -22
- package/dist/types/src/Relation.d.ts.map +1 -1
- package/dist/types/src/Relation.test.d.ts +2 -0
- package/dist/types/src/Relation.test.d.ts.map +1 -0
- package/dist/types/src/SchemaRegistry.d.ts +84 -0
- package/dist/types/src/SchemaRegistry.d.ts.map +1 -0
- package/dist/types/src/Tag.d.ts +17 -0
- package/dist/types/src/Tag.d.ts.map +1 -0
- package/dist/types/src/Type.d.ts +225 -72
- package/dist/types/src/Type.d.ts.map +1 -1
- package/dist/types/src/Type.test.d.ts +2 -0
- package/dist/types/src/Type.test.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +15 -5
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/internal/annotations/annotations.d.ts +170 -0
- package/dist/types/src/internal/annotations/annotations.d.ts.map +1 -0
- package/dist/types/src/internal/annotations/annotations.test.d.ts.map +1 -0
- package/dist/types/src/internal/annotations/index.d.ts +3 -0
- package/dist/types/src/internal/annotations/index.d.ts.map +1 -0
- package/dist/types/src/internal/annotations/util.d.ts +27 -0
- package/dist/types/src/internal/annotations/util.d.ts.map +1 -0
- package/dist/types/src/internal/api/annotations.d.ts +23 -0
- package/dist/types/src/internal/api/annotations.d.ts.map +1 -0
- package/dist/types/src/internal/api/entity.d.ts +13 -0
- package/dist/types/src/internal/api/entity.d.ts.map +1 -0
- package/dist/types/src/internal/api/index.d.ts +15 -0
- package/dist/types/src/internal/api/index.d.ts.map +1 -0
- package/dist/types/src/internal/api/meta.d.ts +42 -0
- package/dist/types/src/internal/api/meta.d.ts.map +1 -0
- package/dist/types/src/internal/api/sorting.d.ts +24 -0
- package/dist/types/src/internal/api/sorting.d.ts.map +1 -0
- package/dist/types/src/internal/api/version.d.ts +42 -0
- package/dist/types/src/internal/api/version.d.ts.map +1 -0
- package/dist/types/src/internal/entities/entity.d.ts +20 -0
- package/dist/types/src/internal/entities/entity.d.ts.map +1 -0
- package/dist/types/src/internal/entities/index.d.ts +6 -0
- package/dist/types/src/internal/entities/index.d.ts.map +1 -0
- package/dist/types/src/internal/entities/model.d.ts +77 -0
- package/dist/types/src/internal/entities/model.d.ts.map +1 -0
- package/dist/types/src/internal/entities/object.d.ts +18 -0
- package/dist/types/src/internal/entities/object.d.ts.map +1 -0
- package/dist/types/src/internal/entities/relation.d.ts +62 -0
- package/dist/types/src/internal/entities/relation.d.ts.map +1 -0
- package/dist/types/src/internal/entities/util.d.ts +2 -0
- package/dist/types/src/internal/entities/util.d.ts.map +1 -0
- package/dist/types/src/internal/formats/format.d.ts +4 -2
- package/dist/types/src/internal/formats/format.d.ts.map +1 -1
- package/dist/types/src/internal/formats/select.d.ts +5 -3
- package/dist/types/src/internal/formats/select.d.ts.map +1 -1
- package/dist/types/src/internal/formats/string.d.ts +4 -0
- package/dist/types/src/internal/formats/string.d.ts.map +1 -1
- package/dist/types/src/internal/formats/types.d.ts +13 -9
- package/dist/types/src/internal/formats/types.d.ts.map +1 -1
- package/dist/types/src/internal/index.d.ts +7 -10
- package/dist/types/src/internal/index.d.ts.map +1 -1
- package/dist/types/src/internal/json-schema/annotations.d.ts.map +1 -0
- package/dist/types/src/internal/json-schema/effect-schema.test.d.ts.map +1 -0
- package/dist/types/src/internal/json-schema/index.d.ts +2 -0
- package/dist/types/src/internal/json-schema/index.d.ts.map +1 -1
- package/dist/types/src/internal/json-schema/json-schema-type.d.ts.map +1 -1
- package/dist/types/src/internal/{json → json-schema}/json-schema.d.ts +2 -1
- package/dist/types/src/internal/json-schema/json-schema.d.ts.map +1 -0
- package/dist/types/src/internal/json-schema/json-schema.test.d.ts.map +1 -0
- package/dist/types/src/internal/object/clone.d.ts +8 -0
- package/dist/types/src/internal/object/clone.d.ts.map +1 -0
- package/dist/types/src/internal/object/common.d.ts.map +1 -1
- package/dist/types/src/internal/object/{create.d.ts → create-object.d.ts} +10 -11
- package/dist/types/src/internal/object/create-object.d.ts.map +1 -0
- package/dist/types/src/internal/object/create-object.test.d.ts +2 -0
- package/dist/types/src/internal/object/create-object.test.d.ts.map +1 -0
- package/dist/types/src/internal/object/deleted.d.ts +2 -2
- package/dist/types/src/internal/object/deleted.d.ts.map +1 -1
- package/dist/types/src/internal/object/ids.d.ts.map +1 -1
- package/dist/types/src/internal/object/index.d.ts +6 -11
- package/dist/types/src/internal/object/index.d.ts.map +1 -1
- package/dist/types/src/internal/object/json-serializer.d.ts +14 -9
- package/dist/types/src/internal/object/json-serializer.d.ts.map +1 -1
- package/dist/types/src/internal/object/schema-validator.d.ts +1 -14
- package/dist/types/src/internal/object/schema-validator.d.ts.map +1 -1
- package/dist/types/src/internal/object/set-value.d.ts +7 -0
- package/dist/types/src/internal/object/set-value.d.ts.map +1 -0
- package/dist/types/src/internal/object/set-value.test.d.ts +2 -0
- package/dist/types/src/internal/object/set-value.test.d.ts.map +1 -0
- package/dist/types/src/internal/object/snapshot.d.ts +6 -0
- package/dist/types/src/internal/object/snapshot.d.ts.map +1 -0
- package/dist/types/src/internal/object/typed-object.d.ts +8 -14
- package/dist/types/src/internal/object/typed-object.d.ts.map +1 -1
- package/dist/types/src/internal/proxy/change-context.d.ts +55 -0
- package/dist/types/src/internal/proxy/change-context.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/change.test.d.ts +2 -0
- package/dist/types/src/internal/proxy/change.test.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/define-hidden-property.d.ts +5 -0
- package/dist/types/src/internal/proxy/define-hidden-property.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/errors.d.ts +19 -0
- package/dist/types/src/internal/proxy/errors.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/event-batch.d.ts +10 -0
- package/dist/types/src/internal/proxy/event-batch.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/index.d.ts +14 -0
- package/dist/types/src/internal/proxy/index.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/json-serializer.d.ts +6 -0
- package/dist/types/src/internal/proxy/json-serializer.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/make-object.d.ts +14 -0
- package/dist/types/src/internal/proxy/make-object.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/ownership.d.ts +57 -0
- package/dist/types/src/internal/proxy/ownership.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/proxy-types.d.ts +18 -0
- package/dist/types/src/internal/proxy/proxy-types.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/proxy-utils.d.ts +47 -0
- package/dist/types/src/internal/proxy/proxy-utils.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/reactive-array.d.ts +8 -0
- package/dist/types/src/internal/proxy/reactive-array.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/reactive.d.ts +39 -0
- package/dist/types/src/internal/proxy/reactive.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/schema-validator.d.ts +15 -0
- package/dist/types/src/internal/proxy/schema-validator.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/symbols.d.ts +3 -0
- package/dist/types/src/internal/proxy/symbols.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/typed-handler.d.ts +15 -12
- package/dist/types/src/internal/proxy/typed-handler.d.ts.map +1 -1
- package/dist/types/src/internal/ref/ref-array.d.ts +4 -4
- package/dist/types/src/internal/ref/ref-array.d.ts.map +1 -1
- package/dist/types/src/internal/ref/ref.d.ts +27 -16
- package/dist/types/src/internal/ref/ref.d.ts.map +1 -1
- package/dist/types/src/internal/schema/compose.d.ts.map +1 -0
- package/dist/types/src/internal/schema/compose.test.d.ts.map +1 -0
- package/dist/types/src/internal/schema/echo-schema.d.ts +24 -12
- package/dist/types/src/internal/schema/echo-schema.d.ts.map +1 -1
- package/dist/types/src/internal/schema/index.d.ts +1 -4
- package/dist/types/src/internal/schema/index.d.ts.map +1 -1
- package/dist/types/src/internal/schema/persistent-schema.d.ts +20 -0
- package/dist/types/src/internal/schema/persistent-schema.d.ts.map +1 -0
- package/dist/types/src/internal/types/base.d.ts +26 -0
- package/dist/types/src/internal/types/base.d.ts.map +1 -0
- package/dist/types/src/internal/types/entity.d.ts +37 -0
- package/dist/types/src/internal/types/entity.d.ts.map +1 -0
- package/dist/types/src/internal/types/index.d.ts +5 -2
- package/dist/types/src/internal/types/index.d.ts.map +1 -1
- package/dist/types/src/internal/{object → types}/meta.d.ts +12 -11
- package/dist/types/src/internal/types/meta.d.ts.map +1 -0
- package/dist/types/src/internal/types/typename.d.ts +13 -0
- package/dist/types/src/internal/types/typename.d.ts.map +1 -0
- package/dist/types/src/internal/{object → types}/version.d.ts +3 -2
- package/dist/types/src/internal/types/version.d.ts.map +1 -0
- package/dist/types/src/{test → testing}/api.test.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +3 -3
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/test-data.d.ts +18 -0
- package/dist/types/src/testing/test-data.d.ts.map +1 -0
- package/dist/types/src/testing/test-schema.d.ts +303 -0
- package/dist/types/src/testing/test-schema.d.ts.map +1 -0
- package/dist/types/src/testing/util.d.ts +21 -0
- package/dist/types/src/testing/util.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +160 -45
- package/src/Annotation.ts +18 -0
- package/src/Database.ts +336 -0
- package/src/Entity.test.ts +22 -0
- package/src/Entity.ts +217 -0
- package/src/{errors.ts → Err.ts} +2 -2
- package/src/Filter.ts +376 -0
- package/src/Format.ts +9 -0
- package/src/Hypergraph.ts +74 -0
- package/src/JsonSchema.ts +16 -0
- package/src/Key.ts +3 -0
- package/src/Obj.test.ts +386 -0
- package/src/Obj.ts +449 -275
- package/src/Order.ts +44 -0
- package/src/Query.test.ts +465 -0
- package/src/Query.ts +296 -0
- package/src/QueryResult.ts +106 -0
- package/src/Ref.ts +26 -9
- package/src/Relation.test.ts +82 -0
- package/src/Relation.ts +411 -60
- package/src/SchemaRegistry.ts +105 -0
- package/src/{query/tag.ts → Tag.ts} +10 -7
- package/src/Type.test.ts +52 -0
- package/src/Type.ts +361 -114
- package/src/index.ts +16 -6
- package/src/internal/README.md +100 -0
- package/src/internal/{ast → annotations}/annotations.test.ts +18 -20
- package/src/internal/annotations/annotations.ts +460 -0
- package/src/internal/annotations/index.ts +6 -0
- package/src/internal/annotations/util.ts +72 -0
- package/src/internal/api/annotations.ts +60 -0
- package/src/internal/api/entity.ts +29 -0
- package/src/internal/api/index.ts +19 -0
- package/src/internal/api/meta.ts +88 -0
- package/src/internal/api/sorting.ts +53 -0
- package/src/internal/api/version.ts +96 -0
- package/src/internal/entities/entity.ts +126 -0
- package/src/internal/entities/index.ts +9 -0
- package/src/internal/entities/model.ts +134 -0
- package/src/internal/entities/object.ts +60 -0
- package/src/internal/entities/relation.ts +173 -0
- package/src/internal/entities/util.ts +33 -0
- package/src/internal/formats/date.test.ts +1 -1
- package/src/internal/formats/date.ts +5 -5
- package/src/internal/formats/format.test.ts +5 -5
- package/src/internal/formats/format.ts +8 -6
- package/src/internal/formats/number.ts +5 -5
- package/src/internal/formats/object.ts +4 -4
- package/src/internal/formats/select.ts +5 -3
- package/src/internal/formats/string.ts +14 -9
- package/src/internal/formats/types.ts +53 -42
- package/src/internal/index.ts +30 -13
- package/src/internal/{json → json-schema}/annotations.ts +1 -1
- package/src/internal/json-schema/index.ts +2 -0
- package/src/internal/json-schema/json-schema-type.ts +5 -4
- package/src/internal/{json → json-schema}/json-schema.test.ts +73 -69
- package/src/internal/{json → json-schema}/json-schema.ts +17 -8
- package/src/internal/object/clone.ts +48 -0
- package/src/internal/object/common.ts +3 -4
- package/src/internal/object/{create.test.ts → create-object.test.ts} +31 -33
- package/src/internal/object/{create.ts → create-object.ts} +36 -37
- package/src/internal/object/deleted.ts +6 -6
- package/src/internal/object/ids.ts +1 -1
- package/src/internal/object/index.ts +6 -11
- package/src/internal/object/inspect.ts +5 -7
- package/src/internal/object/json-serializer.test.ts +35 -37
- package/src/internal/object/json-serializer.ts +65 -102
- package/src/internal/object/schema-validator.ts +2 -237
- package/src/internal/object/set-value.test.ts +281 -0
- package/src/internal/object/set-value.ts +165 -0
- package/src/internal/object/snapshot.ts +70 -0
- package/src/internal/object/typed-object.test.ts +11 -11
- package/src/internal/object/typed-object.ts +8 -66
- package/src/internal/proxy/change-context.ts +138 -0
- package/src/internal/proxy/change.test.ts +519 -0
- package/src/internal/proxy/define-hidden-property.ts +14 -0
- package/src/internal/proxy/errors.ts +42 -0
- package/src/internal/proxy/event-batch.ts +44 -0
- package/src/internal/proxy/handler.test.ts +51 -91
- package/src/internal/proxy/index.ts +17 -0
- package/src/internal/proxy/json-serializer.ts +87 -0
- package/src/internal/proxy/make-object.ts +96 -0
- package/src/internal/proxy/ownership.ts +253 -0
- package/src/internal/proxy/proxy-types.ts +23 -0
- package/src/internal/proxy/proxy-utils.ts +150 -0
- package/src/internal/proxy/reactive-array.ts +71 -0
- package/src/internal/proxy/reactive.ts +69 -0
- package/src/internal/proxy/schema-validator.ts +244 -0
- package/src/internal/proxy/schema.test.ts +27 -18
- package/src/internal/proxy/symbols.ts +7 -0
- package/src/internal/proxy/typed-handler.test.ts +264 -48
- package/src/internal/proxy/typed-handler.ts +275 -61
- package/src/internal/proxy/typed-object.test.ts +43 -27
- package/src/internal/ref/ref-array.ts +4 -4
- package/src/internal/ref/ref.test.ts +9 -8
- package/src/internal/ref/ref.ts +81 -54
- package/src/internal/{projection → schema}/compose.test.ts +8 -9
- package/src/internal/{projection → schema}/compose.ts +1 -1
- package/src/internal/schema/echo-schema.ts +73 -33
- package/src/internal/schema/index.ts +1 -4
- package/src/internal/schema/manipulation.ts +1 -1
- package/src/internal/schema/persistent-schema.ts +27 -0
- package/src/internal/types/base.ts +43 -0
- package/src/internal/types/entity.ts +54 -0
- package/src/internal/types/index.ts +5 -2
- package/src/internal/{object → types}/meta.ts +22 -17
- package/src/internal/types/typename.ts +45 -0
- package/src/internal/types/version.ts +20 -0
- package/src/testing/api.test.ts +126 -0
- package/src/testing/index.ts +3 -3
- package/src/testing/test-data.ts +130 -0
- package/src/testing/test-schema.ts +238 -0
- package/src/testing/util.ts +85 -0
- package/dist/lib/browser/chunk-HKFCK2GL.mjs +0 -175
- package/dist/lib/browser/chunk-HKFCK2GL.mjs.map +0 -7
- package/dist/lib/browser/chunk-MAAYELT7.mjs +0 -830
- package/dist/lib/browser/chunk-MAAYELT7.mjs.map +0 -7
- package/dist/lib/browser/chunk-MB6MMNFP.mjs +0 -3857
- package/dist/lib/browser/chunk-MB6MMNFP.mjs.map +0 -7
- package/dist/lib/browser/query/index.mjs +0 -15
- package/dist/lib/node-esm/chunk-5NWDGIBT.mjs +0 -830
- package/dist/lib/node-esm/chunk-5NWDGIBT.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-AUAH4E2J.mjs +0 -175
- package/dist/lib/node-esm/chunk-AUAH4E2J.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-BQRA4VLX.mjs +0 -3857
- package/dist/lib/node-esm/chunk-BQRA4VLX.mjs.map +0 -7
- package/dist/lib/node-esm/query/index.mjs +0 -15
- package/dist/types/src/errors.d.ts.map +0 -1
- package/dist/types/src/internal/ast/annotation-helper.d.ts +0 -8
- package/dist/types/src/internal/ast/annotation-helper.d.ts.map +0 -1
- package/dist/types/src/internal/ast/annotations.d.ts +0 -125
- package/dist/types/src/internal/ast/annotations.d.ts.map +0 -1
- package/dist/types/src/internal/ast/annotations.test.d.ts.map +0 -1
- package/dist/types/src/internal/ast/entity-kind.d.ts +0 -10
- package/dist/types/src/internal/ast/entity-kind.d.ts.map +0 -1
- package/dist/types/src/internal/ast/index.d.ts +0 -5
- package/dist/types/src/internal/ast/index.d.ts.map +0 -1
- package/dist/types/src/internal/ast/types.d.ts +0 -6
- package/dist/types/src/internal/ast/types.d.ts.map +0 -1
- package/dist/types/src/internal/json/annotations.d.ts.map +0 -1
- package/dist/types/src/internal/json/effect-schema.test.d.ts.map +0 -1
- package/dist/types/src/internal/json/index.d.ts +0 -2
- package/dist/types/src/internal/json/index.d.ts.map +0 -1
- package/dist/types/src/internal/json/json-schema.d.ts.map +0 -1
- package/dist/types/src/internal/json/json-schema.test.d.ts.map +0 -1
- package/dist/types/src/internal/object/accessors.d.ts +0 -37
- package/dist/types/src/internal/object/accessors.d.ts.map +0 -1
- package/dist/types/src/internal/object/create.d.ts.map +0 -1
- package/dist/types/src/internal/object/create.test.d.ts +0 -2
- package/dist/types/src/internal/object/create.test.d.ts.map +0 -1
- package/dist/types/src/internal/object/entity.d.ts +0 -33
- package/dist/types/src/internal/object/entity.d.ts.map +0 -1
- package/dist/types/src/internal/object/expando.d.ts +0 -14
- package/dist/types/src/internal/object/expando.d.ts.map +0 -1
- package/dist/types/src/internal/object/meta.d.ts.map +0 -1
- package/dist/types/src/internal/object/model.d.ts +0 -117
- package/dist/types/src/internal/object/model.d.ts.map +0 -1
- package/dist/types/src/internal/object/relation.d.ts +0 -17
- package/dist/types/src/internal/object/relation.d.ts.map +0 -1
- package/dist/types/src/internal/object/typename.d.ts +0 -15
- package/dist/types/src/internal/object/typename.d.ts.map +0 -1
- package/dist/types/src/internal/object/version.d.ts.map +0 -1
- package/dist/types/src/internal/projection/compose.d.ts.map +0 -1
- package/dist/types/src/internal/projection/compose.test.d.ts.map +0 -1
- package/dist/types/src/internal/projection/index.d.ts +0 -2
- package/dist/types/src/internal/projection/index.d.ts.map +0 -1
- package/dist/types/src/internal/proxy/reactive-object.d.ts +0 -15
- package/dist/types/src/internal/proxy/reactive-object.d.ts.map +0 -1
- package/dist/types/src/internal/query/index.d.ts +0 -2
- package/dist/types/src/internal/query/index.d.ts.map +0 -1
- package/dist/types/src/internal/query/query.d.ts +0 -17
- package/dist/types/src/internal/query/query.d.ts.map +0 -1
- package/dist/types/src/internal/schema/runtime-schema-registry.d.ts +0 -18
- package/dist/types/src/internal/schema/runtime-schema-registry.d.ts.map +0 -1
- package/dist/types/src/internal/schema/snapshot.d.ts +0 -6
- package/dist/types/src/internal/schema/snapshot.d.ts.map +0 -1
- package/dist/types/src/internal/schema/stored-schema.d.ts +0 -13
- package/dist/types/src/internal/schema/stored-schema.d.ts.map +0 -1
- package/dist/types/src/internal/testing/index.d.ts +0 -3
- package/dist/types/src/internal/testing/index.d.ts.map +0 -1
- package/dist/types/src/internal/testing/types.d.ts +0 -455
- package/dist/types/src/internal/testing/types.d.ts.map +0 -1
- package/dist/types/src/internal/testing/utils.d.ts +0 -10
- package/dist/types/src/internal/testing/utils.d.ts.map +0 -1
- package/dist/types/src/internal/types/types.d.ts +0 -79
- package/dist/types/src/internal/types/types.d.ts.map +0 -1
- package/dist/types/src/internal/types/types.test.d.ts +0 -2
- package/dist/types/src/internal/types/types.test.d.ts.map +0 -1
- package/dist/types/src/internal/types/util.d.ts +0 -5
- package/dist/types/src/internal/types/util.d.ts.map +0 -1
- package/dist/types/src/query/index.d.ts +0 -3
- package/dist/types/src/query/index.d.ts.map +0 -1
- package/dist/types/src/query/query.d.ts +0 -248
- package/dist/types/src/query/query.d.ts.map +0 -1
- package/dist/types/src/query/query.test.d.ts +0 -2
- package/dist/types/src/query/query.test.d.ts.map +0 -1
- package/dist/types/src/query/tag.d.ts +0 -17
- package/dist/types/src/query/tag.d.ts.map +0 -1
- package/dist/types/src/testing/echo-schema.d.ts +0 -7
- package/dist/types/src/testing/echo-schema.d.ts.map +0 -1
- package/dist/types/src/testing/types.d.ts +0 -113
- package/dist/types/src/testing/types.d.ts.map +0 -1
- package/src/internal/ast/annotation-helper.ts +0 -22
- package/src/internal/ast/annotations.ts +0 -219
- package/src/internal/ast/entity-kind.ts +0 -15
- package/src/internal/ast/index.ts +0 -8
- package/src/internal/ast/types.ts +0 -17
- package/src/internal/json/index.ts +0 -5
- package/src/internal/object/accessors.ts +0 -153
- package/src/internal/object/entity.ts +0 -248
- package/src/internal/object/expando.ts +0 -21
- package/src/internal/object/model.ts +0 -170
- package/src/internal/object/relation.ts +0 -24
- package/src/internal/object/typename.ts +0 -61
- package/src/internal/object/version.ts +0 -22
- package/src/internal/projection/index.ts +0 -5
- package/src/internal/proxy/reactive-object.ts +0 -108
- package/src/internal/query/index.ts +0 -5
- package/src/internal/query/query.ts +0 -23
- package/src/internal/schema/runtime-schema-registry.ts +0 -78
- package/src/internal/schema/snapshot.ts +0 -25
- package/src/internal/schema/stored-schema.ts +0 -26
- package/src/internal/testing/index.ts +0 -6
- package/src/internal/testing/types.ts +0 -211
- package/src/internal/testing/utils.ts +0 -54
- package/src/internal/types/types.test.ts +0 -48
- package/src/internal/types/types.ts +0 -176
- package/src/internal/types/util.ts +0 -9
- package/src/query/index.ts +0 -6
- package/src/query/query.test.ts +0 -401
- package/src/query/query.ts +0 -789
- package/src/test/api.test.ts +0 -180
- package/src/testing/echo-schema.ts +0 -39
- package/src/testing/types.ts +0 -91
- /package/dist/lib/browser/{query/index.mjs.map → Annotation.mjs.map} +0 -0
- /package/dist/lib/{node-esm/query/index.mjs.map → browser/Database.mjs.map} +0 -0
- /package/dist/types/src/internal/{ast → annotations}/annotations.test.d.ts +0 -0
- /package/dist/types/src/internal/{json → json-schema}/annotations.d.ts +0 -0
- /package/dist/types/src/internal/{json → json-schema}/effect-schema.test.d.ts +0 -0
- /package/dist/types/src/internal/{json → json-schema}/json-schema.test.d.ts +0 -0
- /package/dist/types/src/internal/{projection → schema}/compose.d.ts +0 -0
- /package/dist/types/src/internal/{projection → schema}/compose.test.d.ts +0 -0
- /package/dist/types/src/{test → testing}/api.test.d.ts +0 -0
- /package/src/internal/{json → json-schema}/effect-schema.test.ts +0 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { batchEvents } from './event-batch';
|
|
6
|
+
import { EventId } from './symbols';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Generic change context tracking.
|
|
10
|
+
* Only one object can be in a change context at a time (synchronous changes).
|
|
11
|
+
*
|
|
12
|
+
* This module provides a unified change context mechanism used by both:
|
|
13
|
+
* - TypedReactiveHandler (for non-database objects, using target as key)
|
|
14
|
+
* - EchoReactiveHandler (for database objects, using ObjectCore as key)
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The object currently in a change context.
|
|
19
|
+
* Can be a target object (for typed reactive) or ObjectCore (for database objects).
|
|
20
|
+
*/
|
|
21
|
+
let currentChangeContext: object | null = null;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The primary object that has pending notifications, if any.
|
|
25
|
+
* This uses the contextKey (target or ObjectCore).
|
|
26
|
+
*/
|
|
27
|
+
let pendingNotificationKey: object | null = null;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Additional objects (owner chain) that need notifications.
|
|
31
|
+
* These are separate from the primary notification because they use EventId directly.
|
|
32
|
+
*/
|
|
33
|
+
const pendingOwnerNotifications = new Set<object>();
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Enter a change context for the given key.
|
|
37
|
+
* While in a change context, mutations are allowed on the associated object.
|
|
38
|
+
* Nested Obj.change calls are not supported.
|
|
39
|
+
*
|
|
40
|
+
* @param key - The key to enter the change context for (target object or ObjectCore).
|
|
41
|
+
* @returns A cleanup function that exits the change context.
|
|
42
|
+
*/
|
|
43
|
+
export const enterChangeContext = (key: object): (() => void) => {
|
|
44
|
+
currentChangeContext = key;
|
|
45
|
+
return () => {
|
|
46
|
+
currentChangeContext = null;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Check if the given key is currently in a change context.
|
|
52
|
+
*
|
|
53
|
+
* @param key - The key to check (target object or ObjectCore).
|
|
54
|
+
* @returns True if the key is in a change context, false otherwise.
|
|
55
|
+
*/
|
|
56
|
+
export const isInChangeContext = (key: object): boolean => {
|
|
57
|
+
return currentChangeContext === key;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Queue a notification for the given key to be fired when the change context exits.
|
|
62
|
+
*
|
|
63
|
+
* @param key - The key to queue a notification for.
|
|
64
|
+
*/
|
|
65
|
+
export const queueNotification = (key: object): void => {
|
|
66
|
+
if (currentChangeContext === key) {
|
|
67
|
+
pendingNotificationKey = key;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Queue an owner notification. Owner notifications are for objects in the ownership
|
|
73
|
+
* chain that should be notified when a nested object changes.
|
|
74
|
+
* These objects have EventId and emit directly.
|
|
75
|
+
* Skip if the target is already the current change context (to avoid duplicate notifications).
|
|
76
|
+
*
|
|
77
|
+
* @param target - The owner target that has EventId.
|
|
78
|
+
*/
|
|
79
|
+
export const queueOwnerNotification = (target: object): void => {
|
|
80
|
+
// Skip if this is the object already being changed (primary notification handles it).
|
|
81
|
+
if (currentChangeContext !== null && target !== currentChangeContext) {
|
|
82
|
+
pendingOwnerNotifications.add(target);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Check if there are any pending notifications for the given key.
|
|
88
|
+
*
|
|
89
|
+
* @param key - The key to check.
|
|
90
|
+
* @returns True if there are pending notifications, false otherwise.
|
|
91
|
+
*/
|
|
92
|
+
export const hasPendingNotifications = (key: object): boolean => {
|
|
93
|
+
return pendingNotificationKey === key;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Clear any pending notifications for the given key.
|
|
98
|
+
*
|
|
99
|
+
* @param key - The key to clear notifications for.
|
|
100
|
+
*/
|
|
101
|
+
export const clearPendingNotifications = (key: object): void => {
|
|
102
|
+
if (pendingNotificationKey === key) {
|
|
103
|
+
pendingNotificationKey = null;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Execute a callback within a change context.
|
|
109
|
+
* This is the shared implementation used by both TypedReactiveHandler and EchoReactiveHandler.
|
|
110
|
+
*
|
|
111
|
+
* @param contextKey - The key for the change context (target for typed, ObjectCore for db).
|
|
112
|
+
* @param eventTarget - The object that has the EventId for notifications.
|
|
113
|
+
* @param proxy - The proxy object to pass to the callback.
|
|
114
|
+
* @param callback - The callback to execute with mutations allowed.
|
|
115
|
+
*/
|
|
116
|
+
export const executeChange = (
|
|
117
|
+
contextKey: object,
|
|
118
|
+
eventTarget: object,
|
|
119
|
+
proxy: any,
|
|
120
|
+
callback: (proxy: any) => void,
|
|
121
|
+
): void => {
|
|
122
|
+
const exitContext = enterChangeContext(contextKey);
|
|
123
|
+
try {
|
|
124
|
+
batchEvents(() => callback(proxy));
|
|
125
|
+
} finally {
|
|
126
|
+
exitContext();
|
|
127
|
+
// Fire primary notification.
|
|
128
|
+
if (hasPendingNotifications(contextKey)) {
|
|
129
|
+
clearPendingNotifications(contextKey);
|
|
130
|
+
(eventTarget as any)[EventId]?.emit();
|
|
131
|
+
}
|
|
132
|
+
// Fire owner chain notifications.
|
|
133
|
+
for (const ownerTarget of pendingOwnerNotifications) {
|
|
134
|
+
(ownerTarget as any)[EventId]?.emit();
|
|
135
|
+
}
|
|
136
|
+
pendingOwnerNotifications.clear();
|
|
137
|
+
}
|
|
138
|
+
};
|
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import * as Obj from '../../Obj';
|
|
8
|
+
import * as Relation from '../../Relation';
|
|
9
|
+
import { TestSchema } from '../../testing';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Tests for Obj.change context enforcement and mutator type safety.
|
|
13
|
+
*
|
|
14
|
+
* These tests verify:
|
|
15
|
+
* 1. Mutator functions require Mutable<T> at compile-time.
|
|
16
|
+
* 2. getMeta returns ReadonlyMeta outside change callbacks and ObjectMeta inside.
|
|
17
|
+
* 3. Mutations outside Obj.change throw at runtime.
|
|
18
|
+
* 4. Nested object/property mutations work correctly.
|
|
19
|
+
* 5. Array mutations (push, pop, splice) require change context.
|
|
20
|
+
* 6. Property delete requires change context.
|
|
21
|
+
*/
|
|
22
|
+
describe('Obj.change enforcement', () => {
|
|
23
|
+
describe('compile-time and runtime safety', () => {
|
|
24
|
+
test('direct property mutation outside change throws', ({ expect }) => {
|
|
25
|
+
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
26
|
+
|
|
27
|
+
// Direct property mutation should throw.
|
|
28
|
+
expect(() => {
|
|
29
|
+
// @ts-expect-error Testing runtime error for readonly property mutation.
|
|
30
|
+
obj.name = 'New Name';
|
|
31
|
+
}).toThrow(/outside of Obj.change/);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('Obj.setValue outside change throws', ({ expect }) => {
|
|
35
|
+
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
36
|
+
|
|
37
|
+
// No compile-time error: TypeScript's structural typing allows readonly objects
|
|
38
|
+
// to be passed to Mutable<T> parameters. Enforcement is runtime-only.
|
|
39
|
+
expect(() => Obj.setValue(obj, ['name'], 'value')).toThrow(/outside of Obj.change/);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('Obj.addTag outside change throws', ({ expect }) => {
|
|
43
|
+
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
44
|
+
|
|
45
|
+
// No compile-time error: TypeScript's structural typing allows readonly objects
|
|
46
|
+
// to be passed to Mutable<T> parameters. Enforcement is runtime-only.
|
|
47
|
+
expect(() => Obj.addTag(obj, 'tag')).toThrow(/outside of Obj.change/);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('getMeta mutation outside change throws', ({ expect }) => {
|
|
51
|
+
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
52
|
+
const meta = Obj.getMeta(obj);
|
|
53
|
+
|
|
54
|
+
// Runtime errors for direct meta mutations.
|
|
55
|
+
expect(() => ((meta as any).keys = [])).toThrow(/outside of Obj.change/);
|
|
56
|
+
expect(() => ((meta as any).tags = ['tag'])).toThrow(/outside of Obj.change/);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('getMeta returns mutable ObjectMeta inside change callback', ({ expect }) => {
|
|
60
|
+
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
61
|
+
|
|
62
|
+
Obj.change(obj, (mutableObj) => {
|
|
63
|
+
const meta = Obj.getMeta(mutableObj);
|
|
64
|
+
|
|
65
|
+
// These should compile without errors because meta is ObjectMeta (mutable).
|
|
66
|
+
meta.keys = [];
|
|
67
|
+
meta.tags = ['tag'];
|
|
68
|
+
meta.keys.push({ source: 'test', id: '123' });
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
expect(Obj.getMeta(obj).tags).toEqual(['tag']);
|
|
72
|
+
expect(Obj.getMeta(obj).keys).toHaveLength(1);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test('mutators work inside change callback', ({ expect }) => {
|
|
76
|
+
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
77
|
+
|
|
78
|
+
// These should compile without errors inside change callback.
|
|
79
|
+
Obj.change(obj, (mutableObj) => {
|
|
80
|
+
Obj.addTag(mutableObj, 'my-tag');
|
|
81
|
+
Obj.setValue(mutableObj, ['name'], 'Updated');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
expect(obj.name).toBe('Updated');
|
|
85
|
+
expect(Obj.getMeta(obj).tags).toContain('my-tag');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('Relation property mutation outside change throws', ({ expect }) => {
|
|
89
|
+
const source = Obj.make(TestSchema.Person, { name: 'Alice' });
|
|
90
|
+
const target = Obj.make(TestSchema.Person, { name: 'Bob' });
|
|
91
|
+
const rel = Relation.make(TestSchema.HasManager, {
|
|
92
|
+
[Relation.Source]: source,
|
|
93
|
+
[Relation.Target]: target,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Direct property mutation should throw.
|
|
97
|
+
expect(() => {
|
|
98
|
+
// @ts-expect-error Testing runtime error for readonly property mutation.
|
|
99
|
+
rel.title = 'Manager';
|
|
100
|
+
}).toThrow(/outside of Obj.change/);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('Relation.addTag outside change throws', ({ expect }) => {
|
|
104
|
+
const source = Obj.make(TestSchema.Person, { name: 'Alice' });
|
|
105
|
+
const target = Obj.make(TestSchema.Person, { name: 'Bob' });
|
|
106
|
+
const rel = Relation.make(TestSchema.HasManager, {
|
|
107
|
+
[Relation.Source]: source,
|
|
108
|
+
[Relation.Target]: target,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// No compile-time error: TypeScript's structural typing allows readonly objects
|
|
112
|
+
// to be passed to Mutable<T> parameters. Enforcement is runtime-only.
|
|
113
|
+
expect(() => Relation.addTag(rel, 'tag')).toThrow(/outside of Obj.change/);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe('behavior', () => {
|
|
118
|
+
test('setLabel and getLabel work correctly with Person schema', ({ expect }) => {
|
|
119
|
+
// Person schema has name as the label field.
|
|
120
|
+
const obj = Obj.make(TestSchema.Person, { name: 'John' });
|
|
121
|
+
|
|
122
|
+
// Person schema uses 'name' as label field.
|
|
123
|
+
expect(Obj.getLabel(obj)).toBe('John');
|
|
124
|
+
|
|
125
|
+
Obj.change(obj, (o) => {
|
|
126
|
+
Obj.setLabel(o, 'Jane');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// setLabel updates the name field.
|
|
130
|
+
expect(Obj.getLabel(obj)).toBe('Jane');
|
|
131
|
+
expect(obj.name).toBe('Jane');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test('setDescription works on schemas with description annotation', ({ expect }) => {
|
|
135
|
+
// Person schema may not have a description field, but we can still test the API.
|
|
136
|
+
const obj = Obj.make(TestSchema.Person, { name: 'John' });
|
|
137
|
+
|
|
138
|
+
// Description is undefined if not set.
|
|
139
|
+
expect(Obj.getDescription(obj)).toBeUndefined();
|
|
140
|
+
|
|
141
|
+
// setDescription only works if schema has description annotation.
|
|
142
|
+
// For schemas without it, this is a no-op.
|
|
143
|
+
Obj.change(obj, (o) => {
|
|
144
|
+
Obj.setDescription(o, 'My Description');
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Verify setDescription doesn't throw.
|
|
148
|
+
expect(true).toBe(true);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test('addTag and removeTag work correctly', ({ expect }) => {
|
|
152
|
+
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
153
|
+
|
|
154
|
+
expect(Obj.getMeta(obj).tags).toBeUndefined();
|
|
155
|
+
|
|
156
|
+
Obj.change(obj, (o) => {
|
|
157
|
+
Obj.addTag(o, 'tag-1');
|
|
158
|
+
Obj.addTag(o, 'tag-2');
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
expect(Obj.getMeta(obj).tags).toEqual(['tag-1', 'tag-2']);
|
|
162
|
+
|
|
163
|
+
Obj.change(obj, (o) => {
|
|
164
|
+
Obj.removeTag(o, 'tag-1');
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
expect(Obj.getMeta(obj).tags).toEqual(['tag-2']);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test('deleteKeys removes foreign keys by source', ({ expect }) => {
|
|
171
|
+
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
172
|
+
|
|
173
|
+
Obj.change(obj, (o) => {
|
|
174
|
+
const meta = Obj.getMeta(o);
|
|
175
|
+
meta.keys.push({ source: 'source-a', id: '1' });
|
|
176
|
+
meta.keys.push({ source: 'source-a', id: '2' });
|
|
177
|
+
meta.keys.push({ source: 'source-b', id: '3' });
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
expect(Obj.getMeta(obj).keys).toHaveLength(3);
|
|
181
|
+
|
|
182
|
+
Obj.change(obj, (o) => {
|
|
183
|
+
Obj.deleteKeys(o, 'source-a');
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
expect(Obj.getMeta(obj).keys).toHaveLength(1);
|
|
187
|
+
expect(Obj.getMeta(obj).keys[0].source).toBe('source-b');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
test('setValue sets nested properties', ({ expect }) => {
|
|
191
|
+
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
192
|
+
|
|
193
|
+
Obj.change(obj, (o) => {
|
|
194
|
+
Obj.setValue(o, ['name'], 'Updated Name');
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
expect(obj.name).toBe('Updated Name');
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test('getMeta is mutable inside change and changes persist', ({ expect }) => {
|
|
201
|
+
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
202
|
+
|
|
203
|
+
Obj.change(obj, (o) => {
|
|
204
|
+
const meta = Obj.getMeta(o);
|
|
205
|
+
meta.tags = ['tag-1', 'tag-2'];
|
|
206
|
+
meta.keys.push({ source: 'external', id: '123' });
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Changes should persist after the change callback.
|
|
210
|
+
expect(Obj.getMeta(obj).tags).toEqual(['tag-1', 'tag-2']);
|
|
211
|
+
expect(Obj.getMeta(obj).keys).toEqual([{ source: 'external', id: '123' }]);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test('multiple mutations in single change all persist', ({ expect }) => {
|
|
215
|
+
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
216
|
+
|
|
217
|
+
Obj.change(obj, (o) => {
|
|
218
|
+
o.name = 'Name 1';
|
|
219
|
+
o.name = 'Name 2';
|
|
220
|
+
o.name = 'Name 3';
|
|
221
|
+
Obj.addTag(o, 'tag-1');
|
|
222
|
+
Obj.addTag(o, 'tag-2');
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// All mutations should persist.
|
|
226
|
+
expect(obj.name).toBe('Name 3');
|
|
227
|
+
expect(Obj.getMeta(obj).tags).toEqual(['tag-1', 'tag-2']);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
describe('notifications', () => {
|
|
232
|
+
test('batched notifications - only one per Obj.change', ({ expect }) => {
|
|
233
|
+
const obj = Obj.make(TestSchema.Person, { name: 'John' });
|
|
234
|
+
|
|
235
|
+
let notificationCount = 0;
|
|
236
|
+
const unsubscribe = Obj.subscribe(obj, () => {
|
|
237
|
+
notificationCount++;
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
Obj.change(obj, (p) => {
|
|
241
|
+
p.name = 'Jane';
|
|
242
|
+
p.age = 30;
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Should only fire one notification for all changes.
|
|
246
|
+
expect(notificationCount).toBe(1);
|
|
247
|
+
|
|
248
|
+
unsubscribe();
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
describe('nested mutations', () => {
|
|
253
|
+
test('nested object property mutation within Obj.change', ({ expect }) => {
|
|
254
|
+
const obj = Obj.make(TestSchema.Person, {
|
|
255
|
+
name: 'John',
|
|
256
|
+
address: { city: 'NYC', coordinates: {} },
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
Obj.change(obj, (p) => {
|
|
260
|
+
p.address!.state = 'NY';
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
expect(obj.address?.state).toBe('NY');
|
|
264
|
+
expect(obj.address?.city).toBe('NYC');
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
test('deeply nested property mutation within Obj.change (2 levels)', ({ expect }) => {
|
|
268
|
+
const obj = Obj.make(TestSchema.Person, {
|
|
269
|
+
name: 'John',
|
|
270
|
+
address: { city: 'NYC', coordinates: { lat: 40.7128, lng: -74.006 } },
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
Obj.change(obj, (p) => {
|
|
274
|
+
p.address!.coordinates!.lat = 51.5074;
|
|
275
|
+
p.address!.coordinates!.lng = -0.1278;
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
expect(obj.address?.coordinates?.lat).toBe(51.5074);
|
|
279
|
+
expect(obj.address?.coordinates?.lng).toBe(-0.1278);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
test('nested object mutation outside Obj.change throws (1 level deep)', ({ expect }) => {
|
|
283
|
+
const obj = Obj.make(TestSchema.Person, {
|
|
284
|
+
name: 'John',
|
|
285
|
+
address: { city: 'NYC', coordinates: {} },
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
expect(() => {
|
|
289
|
+
// @ts-expect-error - nested property assignment is readonly.
|
|
290
|
+
obj.address!.city = 'LA';
|
|
291
|
+
}).toThrow(/outside of Obj.change/);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
test('deeply nested mutation outside Obj.change throws (2 levels deep)', ({ expect }) => {
|
|
295
|
+
const obj = Obj.make(TestSchema.Person, {
|
|
296
|
+
name: 'John',
|
|
297
|
+
address: { city: 'NYC', coordinates: { lat: 40.7128, lng: -74.006 } },
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
expect(() => {
|
|
301
|
+
// @ts-expect-error - deeply nested property assignment should be caught.
|
|
302
|
+
obj.address!.coordinates!.lat = 0;
|
|
303
|
+
}).toThrow(/outside of Obj.change/);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
test('nested Obj.change calls work correctly', ({ expect }) => {
|
|
307
|
+
const obj = Obj.make(TestSchema.Person, { name: 'John' });
|
|
308
|
+
|
|
309
|
+
Obj.change(obj, (p) => {
|
|
310
|
+
p.name = 'Jane';
|
|
311
|
+
|
|
312
|
+
// Nested change should work (already in change context).
|
|
313
|
+
Obj.change(obj, (p2) => {
|
|
314
|
+
p2.age = 30;
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
expect(obj.name).toBe('Jane');
|
|
319
|
+
expect(obj.age).toBe(30);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
test('error in callback does not leave object in broken state', ({ expect }) => {
|
|
323
|
+
const obj = Obj.make(TestSchema.Person, { name: 'John' });
|
|
324
|
+
|
|
325
|
+
expect(() => {
|
|
326
|
+
Obj.change(obj, (p) => {
|
|
327
|
+
p.name = 'Jane';
|
|
328
|
+
throw new Error('Test error');
|
|
329
|
+
});
|
|
330
|
+
}).toThrow('Test error');
|
|
331
|
+
|
|
332
|
+
// Object should still be readonly after error.
|
|
333
|
+
expect(() => {
|
|
334
|
+
// @ts-expect-error Testing runtime error for readonly property mutation.
|
|
335
|
+
obj.name = 'Bob';
|
|
336
|
+
}).toThrow(/outside of Obj.change/);
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
describe('array mutations', () => {
|
|
341
|
+
test('array push within Obj.change', ({ expect }) => {
|
|
342
|
+
const obj = Obj.make(TestSchema.Person, {
|
|
343
|
+
name: 'John',
|
|
344
|
+
fields: [{ label: 'tag1', value: 'val1' }],
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
Obj.change(obj, (p) => {
|
|
348
|
+
p.fields!.push({ label: 'tag2', value: 'val2' });
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
expect(obj.fields).toHaveLength(2);
|
|
352
|
+
expect(obj.fields![1].label).toBe('tag2');
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
test('array pop within Obj.change', ({ expect }) => {
|
|
356
|
+
const obj = Obj.make(TestSchema.Person, {
|
|
357
|
+
name: 'John',
|
|
358
|
+
fields: [
|
|
359
|
+
{ label: 'a', value: '1' },
|
|
360
|
+
{ label: 'b', value: '2' },
|
|
361
|
+
],
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
let popped: any;
|
|
365
|
+
Obj.change(obj, (p) => {
|
|
366
|
+
popped = p.fields!.pop();
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
expect(popped.label).toBe('b');
|
|
370
|
+
expect(obj.fields).toHaveLength(1);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
test('array splice within Obj.change', ({ expect }) => {
|
|
374
|
+
const obj = Obj.make(TestSchema.Person, {
|
|
375
|
+
name: 'John',
|
|
376
|
+
fields: [
|
|
377
|
+
{ label: 'a', value: '1' },
|
|
378
|
+
{ label: 'b', value: '2' },
|
|
379
|
+
{ label: 'c', value: '3' },
|
|
380
|
+
],
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
Obj.change(obj, (p) => {
|
|
384
|
+
p.fields!.splice(1, 1, { label: 'x', value: 'x' });
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
expect(obj.fields).toHaveLength(3);
|
|
388
|
+
expect(obj.fields![1].label).toBe('x');
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
test('array push outside Obj.change throws', ({ expect }) => {
|
|
392
|
+
const obj = Obj.make(TestSchema.Person, {
|
|
393
|
+
name: 'John',
|
|
394
|
+
fields: [{ label: 'tag1', value: 'val1' }],
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
expect(() => {
|
|
398
|
+
// @ts-expect-error Testing runtime error for readonly array mutation.
|
|
399
|
+
obj.fields!.push({ label: 'tag2', value: 'val2' });
|
|
400
|
+
}).toThrow(/array\.push\(\).*outside of Obj\.change/);
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
test('array pop outside Obj.change throws', ({ expect }) => {
|
|
404
|
+
const obj = Obj.make(TestSchema.Person, {
|
|
405
|
+
name: 'John',
|
|
406
|
+
fields: [{ label: 'tag1', value: 'val1' }],
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
expect(() => {
|
|
410
|
+
// @ts-expect-error Testing runtime error for readonly array mutation.
|
|
411
|
+
obj.fields!.pop();
|
|
412
|
+
}).toThrow(/array\.pop\(\).*outside of Obj\.change/);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
test('array splice outside Obj.change throws', ({ expect }) => {
|
|
416
|
+
const obj = Obj.make(TestSchema.Person, {
|
|
417
|
+
name: 'John',
|
|
418
|
+
fields: [{ label: 'tag1', value: 'val1' }],
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
expect(() => {
|
|
422
|
+
// @ts-expect-error Testing runtime error for readonly array mutation.
|
|
423
|
+
obj.fields!.splice(0, 1);
|
|
424
|
+
}).toThrow(/array\.splice\(\).*outside of Obj\.change/);
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
describe('property delete', () => {
|
|
429
|
+
test('delete property within Obj.change', ({ expect }) => {
|
|
430
|
+
const obj = Obj.make(TestSchema.Person, { name: 'John', age: 25 });
|
|
431
|
+
|
|
432
|
+
Obj.change(obj, (p) => {
|
|
433
|
+
delete p.age;
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
expect(obj.age).toBeUndefined();
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
test('delete property outside Obj.change throws', ({ expect }) => {
|
|
440
|
+
const obj = Obj.make(TestSchema.Person, { name: 'John', age: 25 });
|
|
441
|
+
|
|
442
|
+
expect(() => {
|
|
443
|
+
// @ts-expect-error Testing runtime error for readonly property delete.
|
|
444
|
+
delete obj.age;
|
|
445
|
+
}).toThrow(/delete object property.*outside of Obj\.change/);
|
|
446
|
+
});
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
describe('Relation mutators', () => {
|
|
450
|
+
test('Relation.getMeta is mutable inside Relation.change', ({ expect }) => {
|
|
451
|
+
const source = Obj.make(TestSchema.Person, { name: 'Alice' });
|
|
452
|
+
const target = Obj.make(TestSchema.Person, { name: 'Bob' });
|
|
453
|
+
const rel = Relation.make(TestSchema.HasManager, {
|
|
454
|
+
[Relation.Source]: source,
|
|
455
|
+
[Relation.Target]: target,
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
Relation.change(rel, (r) => {
|
|
459
|
+
const meta = Relation.getMeta(r);
|
|
460
|
+
meta.tags = ['rel-tag'];
|
|
461
|
+
meta.keys.push({ source: 'rel-source', id: 'rel-key' });
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
expect(Relation.getMeta(rel).tags).toEqual(['rel-tag']);
|
|
465
|
+
expect(Relation.getMeta(rel).keys).toHaveLength(1);
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
test('Relation mutators work inside change callback', ({ expect }) => {
|
|
469
|
+
const source = Obj.make(TestSchema.Person, { name: 'Alice' });
|
|
470
|
+
const target = Obj.make(TestSchema.Person, { name: 'Bob' });
|
|
471
|
+
const rel = Relation.make(TestSchema.HasManager, {
|
|
472
|
+
[Relation.Source]: source,
|
|
473
|
+
[Relation.Target]: target,
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
Relation.change(rel, (r) => {
|
|
477
|
+
Relation.addTag(r, 'important');
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
expect(Relation.getMeta(rel).tags).toContain('important');
|
|
481
|
+
|
|
482
|
+
Relation.change(rel, (r) => {
|
|
483
|
+
Relation.removeTag(r, 'important');
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
expect(Relation.getMeta(rel).tags).not.toContain('important');
|
|
487
|
+
});
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
describe('object references', () => {
|
|
491
|
+
test('assigning root ECHO objects directly throws - must use Ref.make', ({ expect }) => {
|
|
492
|
+
const obj = Obj.make(TestSchema.Expando, {});
|
|
493
|
+
const other = Obj.make(TestSchema.Expando, { string: 'bar' });
|
|
494
|
+
|
|
495
|
+
// Direct assignment of root ECHO objects (created with Obj.make) is not allowed.
|
|
496
|
+
expect(() => {
|
|
497
|
+
Obj.change(obj, (o) => {
|
|
498
|
+
o.other = other;
|
|
499
|
+
});
|
|
500
|
+
}).toThrow(/Object references must be wrapped with `Ref\.make`/);
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
test('plain nested objects use parent change context', ({ expect }) => {
|
|
504
|
+
const obj = Obj.make(TestSchema.Expando, {});
|
|
505
|
+
|
|
506
|
+
// Assign a plain object (not created with Obj.make).
|
|
507
|
+
Obj.change(obj, (o) => {
|
|
508
|
+
o.nested = { value: 'initial' };
|
|
509
|
+
});
|
|
510
|
+
expect(obj.nested.value).toBe('initial');
|
|
511
|
+
|
|
512
|
+
// Modify plain nested object through parent's change context.
|
|
513
|
+
Obj.change(obj, (o) => {
|
|
514
|
+
o.nested.value = 'modified';
|
|
515
|
+
});
|
|
516
|
+
expect(obj.nested.value).toBe('modified');
|
|
517
|
+
});
|
|
518
|
+
});
|
|
519
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Define a non-enumerable property on an object.
|
|
7
|
+
*/
|
|
8
|
+
export const defineHiddenProperty = (object: any, key: string | symbol, value: any) => {
|
|
9
|
+
Object.defineProperty(object, key, {
|
|
10
|
+
enumerable: false,
|
|
11
|
+
configurable: true,
|
|
12
|
+
value,
|
|
13
|
+
});
|
|
14
|
+
};
|