@dxos/echo 0.8.4-main.bc674ce → 0.8.4-main.bcb3aa67d6
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 +2 -2
- package/dist/lib/neutral/Annotation.mjs +8 -3
- package/dist/lib/neutral/Database.mjs +36 -6
- package/dist/lib/neutral/Entity.mjs +18 -10
- package/dist/lib/neutral/Err.mjs +3 -1
- package/dist/lib/neutral/Extension.mjs +18 -0
- package/dist/lib/neutral/Extension.mjs.map +7 -0
- package/dist/lib/neutral/Feed.mjs +45 -0
- package/dist/lib/neutral/Feed.mjs.map +7 -0
- package/dist/lib/neutral/Filter.mjs +19 -10
- package/dist/lib/neutral/Format.mjs +3 -3
- package/dist/lib/neutral/JsonSchema.mjs +9 -9
- package/dist/lib/neutral/Obj.mjs +35 -15
- package/dist/lib/neutral/Order.mjs +1 -1
- package/dist/lib/neutral/Query.mjs +21 -9
- package/dist/lib/neutral/Ref.mjs +9 -7
- package/dist/lib/neutral/Relation.mjs +20 -11
- package/dist/lib/neutral/SchemaRegistry.mjs +1 -1
- package/dist/lib/neutral/Tag.mjs +13 -10
- package/dist/lib/neutral/Type.mjs +13 -23
- package/dist/lib/neutral/chunk-24XI6DOL.mjs +34 -0
- package/dist/lib/neutral/chunk-24XI6DOL.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-VB5HVDCA.mjs → chunk-4YAAHG3E.mjs} +53 -5
- package/dist/lib/neutral/chunk-4YAAHG3E.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-CUDIBUM4.mjs → chunk-4ZRIO2QF.mjs} +104 -25
- package/dist/lib/neutral/chunk-4ZRIO2QF.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-SU2LVM7J.mjs → chunk-7C2A2RP6.mjs} +1731 -2747
- package/dist/lib/neutral/chunk-7C2A2RP6.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-4L6DOFXP.mjs → chunk-BNCCGLJN.mjs} +1 -1
- package/dist/lib/neutral/{chunk-4L6DOFXP.mjs.map → chunk-BNCCGLJN.mjs.map} +1 -1
- package/dist/lib/neutral/{chunk-2MTHJ5UW.mjs → chunk-CAB5PWUF.mjs} +134 -24
- package/dist/lib/neutral/chunk-CAB5PWUF.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-62DWJ6CE.mjs → chunk-DQYLD2RB.mjs} +14 -14
- package/dist/lib/neutral/chunk-DQYLD2RB.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-XMIDBDE6.mjs → chunk-DUTD5HFU.mjs} +11 -56
- package/dist/lib/neutral/chunk-DUTD5HFU.mjs.map +7 -0
- package/dist/lib/neutral/chunk-EKQJGGA3.mjs +396 -0
- package/dist/lib/neutral/chunk-EKQJGGA3.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-VR4A4WGG.mjs → chunk-EOIR5O5I.mjs} +72 -23
- package/dist/lib/neutral/chunk-EOIR5O5I.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-HMOXCO27.mjs → chunk-GVY6O76A.mjs} +8 -3
- package/dist/lib/neutral/chunk-GVY6O76A.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-4TT624YA.mjs → chunk-GZQTCRJB.mjs} +2 -2
- package/dist/lib/neutral/{chunk-4TT624YA.mjs.map → chunk-GZQTCRJB.mjs.map} +1 -1
- package/dist/lib/neutral/chunk-HGHJ36DH.mjs +117 -0
- package/dist/lib/neutral/chunk-HGHJ36DH.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-3ZEAZF7T.mjs → chunk-IICPQK3M.mjs} +8 -4
- package/dist/lib/neutral/chunk-IICPQK3M.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-IP2GHXWA.mjs → chunk-NKPWM67P.mjs} +5 -5
- package/dist/lib/neutral/chunk-NKPWM67P.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-6QPSGMEF.mjs → chunk-OPMZTWI3.mjs} +32 -8
- package/dist/lib/neutral/chunk-OPMZTWI3.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-NWUO5FKZ.mjs → chunk-OPQEHU36.mjs} +8 -2
- package/dist/lib/neutral/chunk-OPQEHU36.mjs.map +7 -0
- package/dist/lib/neutral/chunk-QDV7C7VM.mjs +299 -0
- package/dist/lib/neutral/chunk-QDV7C7VM.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-YQYMWZAD.mjs → chunk-TBKX6JQO.mjs} +4 -4
- package/dist/lib/neutral/chunk-TBKX6JQO.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-RPB6V4BE.mjs → chunk-UBEZSGXY.mjs} +14 -1
- package/dist/lib/neutral/chunk-UBEZSGXY.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-ROKO4RKJ.mjs → chunk-UI6MWK5W.mjs} +2 -2
- package/dist/lib/neutral/chunk-UI6MWK5W.mjs.map +7 -0
- package/dist/lib/neutral/chunk-XV5R2XZH.mjs +133 -0
- package/dist/lib/neutral/chunk-XV5R2XZH.mjs.map +7 -0
- package/dist/lib/neutral/chunk-YPGDBRPH.mjs +159 -0
- package/dist/lib/neutral/chunk-YPGDBRPH.mjs.map +7 -0
- package/dist/lib/neutral/chunk-YS6Q3XAD.mjs +50 -0
- package/dist/lib/neutral/chunk-YS6Q3XAD.mjs.map +7 -0
- package/dist/lib/neutral/chunk-ZCBOJ6I7.mjs +787 -0
- package/dist/lib/neutral/chunk-ZCBOJ6I7.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +42 -25
- package/dist/lib/neutral/internal/index.mjs +56 -38
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/testing/index.mjs +42 -34
- package/dist/lib/neutral/testing/index.mjs.map +3 -3
- package/dist/types/src/Annotation.d.ts +23 -1
- package/dist/types/src/Annotation.d.ts.map +1 -1
- package/dist/types/src/Collection.d.ts +16 -0
- package/dist/types/src/Collection.d.ts.map +1 -0
- package/dist/types/src/Database.d.ts +86 -84
- package/dist/types/src/Database.d.ts.map +1 -1
- package/dist/types/src/Dataset.d.ts +19 -0
- package/dist/types/src/Dataset.d.ts.map +1 -0
- package/dist/types/src/Entity.d.ts +41 -15
- package/dist/types/src/Entity.d.ts.map +1 -1
- package/dist/types/src/Err.d.ts +43 -0
- 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 +163 -0
- package/dist/types/src/Feed.d.ts.map +1 -0
- package/dist/types/src/Filter.d.ts +21 -5
- 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 +3 -3
- package/dist/types/src/Format.d.ts.map +1 -1
- package/dist/types/src/Hypergraph.d.ts +8 -3
- package/dist/types/src/Hypergraph.d.ts.map +1 -1
- package/dist/types/src/JsonSchema.d.ts +11 -4
- package/dist/types/src/JsonSchema.d.ts.map +1 -1
- package/dist/types/src/Obj.d.ts +158 -43
- 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 +109 -15
- package/dist/types/src/Query.d.ts.map +1 -1
- package/dist/types/src/Ref.d.ts +58 -10
- package/dist/types/src/Ref.d.ts.map +1 -1
- package/dist/types/src/Relation.d.ts +75 -28
- package/dist/types/src/Relation.d.ts.map +1 -1
- package/dist/types/src/SchemaRegistry.d.ts +4 -4
- package/dist/types/src/SchemaRegistry.d.ts.map +1 -1
- package/dist/types/src/Tag.d.ts +4 -3
- package/dist/types/src/Tag.d.ts.map +1 -1
- package/dist/types/src/Type.d.ts +51 -180
- package/dist/types/src/Type.d.ts.map +1 -1
- package/dist/types/src/View.d.ts +68 -0
- package/dist/types/src/View.d.ts.map +1 -0
- package/dist/types/src/hierarchy.test.d.ts +2 -0
- package/dist/types/src/hierarchy.test.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +5 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/internal/{annotations → Annotation}/annotations.d.ts +69 -8
- 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 +13 -1
- 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 +3 -3
- 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 +4 -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 +19 -19
- package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts.map +1 -0
- 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 +12 -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 +1 -1
- 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 +4 -4
- 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 +16 -3
- 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 +8 -7
- 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/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/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/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/common/proxy/reactive-array.d.ts.map +1 -0
- package/dist/types/src/internal/{proxy → common/proxy}/reactive.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/reactive.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/{proxy → common/proxy}/typed-handler.d.ts +2 -1
- 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/{types → common/types}/base.d.ts +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 +2 -2
- 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 +2 -1
- 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/{types → common/types}/typename.d.ts +8 -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 +2 -2
- 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-schema.d.ts +19 -18
- package/dist/types/src/testing/test-schema.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +24 -14
- package/src/Annotation.ts +31 -1
- package/src/Collection.ts +37 -0
- package/src/Database.ts +167 -173
- package/src/Dataset.ts +26 -0
- package/src/Entity.ts +73 -54
- package/src/Err.ts +22 -0
- package/src/Extension.test.ts +235 -0
- package/src/Extension.ts +122 -0
- package/src/Feed.ts +268 -0
- package/src/Filter.test.ts +90 -0
- package/src/Filter.ts +55 -7
- package/src/Format.ts +3 -3
- package/src/Hypergraph.ts +9 -4
- package/src/JsonSchema.ts +14 -4
- package/src/Obj.test.ts +69 -8
- package/src/Obj.ts +285 -140
- package/src/Order.ts +3 -1
- package/src/Query.test.ts +248 -15
- package/src/Query.ts +275 -24
- package/src/Ref.ts +64 -11
- package/src/Relation.test.ts +8 -2
- package/src/Relation.ts +165 -131
- package/src/SchemaRegistry.ts +5 -4
- package/src/Tag.ts +6 -5
- package/src/Type.test.ts +10 -10
- package/src/Type.ts +70 -303
- package/src/View.ts +107 -0
- package/src/hierarchy.test.ts +33 -0
- package/src/index.ts +5 -0
- package/src/internal/{annotations → Annotation}/annotations.test.ts +56 -6
- package/src/internal/{annotations → Annotation}/annotations.ts +134 -15
- package/src/internal/{annotations → Annotation}/index.ts +1 -0
- package/src/internal/{api → Annotation}/sorting.ts +2 -3
- package/src/internal/{annotations → Annotation}/util.ts +14 -1
- package/src/internal/{api/entity.ts → Entity/api.ts} +4 -2
- package/src/internal/{entities → Entity}/entity.ts +6 -4
- package/src/internal/{entities → Entity}/index.ts +2 -0
- package/src/internal/{entities → Entity}/model.ts +17 -42
- package/src/internal/{entities → Entity}/object.ts +2 -2
- package/src/internal/{entities → Entity}/relation.ts +19 -36
- package/src/internal/{api → Entity}/version.ts +3 -2
- package/src/internal/{formats → Format}/date.test.ts +1 -1
- package/src/internal/{formats → Format}/format.test.ts +1 -1
- package/src/internal/{formats → Format}/types.ts +3 -3
- 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 -48
- package/src/internal/{json-schema → JsonSchema}/json-schema.ts +6 -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 +4 -4
- package/src/internal/{object → Obj}/create-object.ts +5 -5
- 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 +31 -8
- package/src/internal/{object → Obj}/json-serializer.ts +42 -15
- 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 +2 -2
- package/src/internal/Obj/snapshot.ts +105 -0
- package/src/internal/{object → Obj}/typed-object.test.ts +3 -3
- package/src/internal/{object → Obj}/typed-object.ts +4 -4
- package/src/internal/Query.ts +132 -0
- package/src/internal/{ref → Ref}/ref-array.ts +1 -1
- package/src/internal/{ref → Ref}/ref.test.ts +4 -4
- package/src/internal/{ref → Ref}/ref.ts +27 -4
- package/src/internal/{schema → Type}/compose.test.ts +5 -5
- package/src/internal/{schema → Type}/compose.ts +1 -1
- package/src/internal/{schema → Type}/echo-schema.ts +11 -10
- package/src/internal/{schema → Type}/manipulation.ts +1 -1
- package/src/internal/{schema → Type}/persistent-schema.ts +10 -4
- package/src/internal/{README.md → common/README.md} +1 -1
- package/src/internal/{api → common/api}/index.ts +0 -4
- package/src/internal/common/index.ts +7 -0
- package/src/internal/{proxy → common/proxy}/change.test.ts +58 -58
- package/src/internal/{proxy → common/proxy}/handler.test.ts +2 -2
- package/src/internal/{proxy → common/proxy}/json-serializer.ts +6 -3
- package/src/internal/{proxy → common/proxy}/make-object.ts +13 -3
- package/src/internal/{proxy → common/proxy}/reactive.ts +1 -1
- package/src/internal/{proxy → common/proxy}/schema.test.ts +10 -10
- package/src/internal/{proxy → common/proxy}/typed-handler.test.ts +6 -6
- package/src/internal/{proxy → common/proxy}/typed-handler.ts +10 -3
- package/src/internal/{proxy → common/proxy}/typed-object.test.ts +4 -4
- package/src/internal/{types → common/types}/base.ts +1 -1
- package/src/internal/{types → common/types}/entity.ts +2 -2
- package/src/internal/{types → common/types}/index.ts +1 -0
- package/src/internal/{types → common/types}/meta.ts +4 -1
- package/src/internal/common/types/model-symbols.ts +69 -0
- package/src/internal/{types → common/types}/typename.ts +10 -0
- package/src/internal/{types → common/types}/version.ts +2 -3
- package/src/internal/index.ts +9 -31
- package/src/testing/api.test.ts +4 -4
- package/src/testing/test-schema.ts +20 -18
- package/dist/lib/neutral/chunk-2MTHJ5UW.mjs.map +0 -7
- package/dist/lib/neutral/chunk-3ZEAZF7T.mjs.map +0 -7
- package/dist/lib/neutral/chunk-62DWJ6CE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-6QPSGMEF.mjs.map +0 -7
- package/dist/lib/neutral/chunk-CUDIBUM4.mjs.map +0 -7
- package/dist/lib/neutral/chunk-HMOXCO27.mjs.map +0 -7
- package/dist/lib/neutral/chunk-IP2GHXWA.mjs.map +0 -7
- package/dist/lib/neutral/chunk-KRHDMXSU.mjs +0 -132
- package/dist/lib/neutral/chunk-KRHDMXSU.mjs.map +0 -7
- package/dist/lib/neutral/chunk-NWUO5FKZ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-ROKO4RKJ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-RPB6V4BE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-SU2LVM7J.mjs.map +0 -7
- package/dist/lib/neutral/chunk-VB5HVDCA.mjs.map +0 -7
- package/dist/lib/neutral/chunk-VR4A4WGG.mjs.map +0 -7
- package/dist/lib/neutral/chunk-X2MPMYYN.mjs +0 -13
- package/dist/lib/neutral/chunk-X2MPMYYN.mjs.map +0 -7
- package/dist/lib/neutral/chunk-XK5OUUBY.mjs +0 -157
- package/dist/lib/neutral/chunk-XK5OUUBY.mjs.map +0 -7
- package/dist/lib/neutral/chunk-XMIDBDE6.mjs.map +0 -7
- package/dist/lib/neutral/chunk-YQYMWZAD.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/reactive.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/src/internal/object/snapshot.ts +0 -70
- /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.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/{api → common/api}/meta.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/change-context.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}/errors.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}/reactive-array.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.test.d.ts +0 -0
- /package/dist/types/src/internal/{proxy → common/proxy}/typed-object.test.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/{api → common/api}/meta.ts +0 -0
- /package/src/internal/{proxy → common/proxy}/change-context.ts +0 -0
- /package/src/internal/{proxy → common/proxy}/define-hidden-property.ts +0 -0
- /package/src/internal/{proxy → common/proxy}/errors.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}/ownership.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}/reactive-array.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/Feed.ts
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
// @import-as-namespace
|
|
6
|
+
|
|
7
|
+
import * as Context from 'effect/Context';
|
|
8
|
+
import * as Effect from 'effect/Effect';
|
|
9
|
+
import * as Layer from 'effect/Layer';
|
|
10
|
+
import type * as Option from 'effect/Option';
|
|
11
|
+
import * as Schema from 'effect/Schema';
|
|
12
|
+
|
|
13
|
+
import { DXN } from '@dxos/keys';
|
|
14
|
+
|
|
15
|
+
import type * as Entity from './Entity';
|
|
16
|
+
import type * as Filter from './Filter';
|
|
17
|
+
import * as internal from './internal';
|
|
18
|
+
import * as Obj from './Obj';
|
|
19
|
+
import type * as Query from './Query';
|
|
20
|
+
import type * as QueryResult from './QueryResult';
|
|
21
|
+
import * as Type from './Type';
|
|
22
|
+
import * as Annotation from './Annotation';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Runtime schema for a Feed object.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* const feed = Obj.make(Feed.Feed, { name: 'notifications', kind: 'org.dxos.plugin.notifications.v1' });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export const Feed = Schema.Struct({
|
|
33
|
+
/** User-facing display name. */
|
|
34
|
+
name: Schema.String.pipe(Schema.optional),
|
|
35
|
+
/** Identifier for the feed's kind (e.g., plugin id). */
|
|
36
|
+
kind: Schema.String.pipe(internal.FormInputAnnotation.set(false), Schema.optional),
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Feed namespace.
|
|
40
|
+
* Controls how feed data is stored and replicated.
|
|
41
|
+
* - `data`: Data feed (default).
|
|
42
|
+
* - `trace`: Trace feed.
|
|
43
|
+
*/
|
|
44
|
+
namespace: Schema.optional(Schema.Literal('data', 'trace')),
|
|
45
|
+
}).pipe(
|
|
46
|
+
Type.object({
|
|
47
|
+
typename: 'org.dxos.type.feed',
|
|
48
|
+
version: '0.1.0',
|
|
49
|
+
}),
|
|
50
|
+
internal.SystemTypeAnnotation.set(true),
|
|
51
|
+
Annotation.IconAnnotation.set({
|
|
52
|
+
icon: 'ph--rows--regular',
|
|
53
|
+
hue: 'yellow',
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* TypeScript instance type for a Feed object.
|
|
59
|
+
*/
|
|
60
|
+
export interface Feed extends Schema.Schema.Type<typeof Feed> {}
|
|
61
|
+
|
|
62
|
+
//
|
|
63
|
+
// Types
|
|
64
|
+
//
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Opaque cursor for iterating over feed items.
|
|
68
|
+
*/
|
|
69
|
+
// TODO(dmaretskyi): T needs to be referenced in the type structure for typescript to respect it during inference and type-checking.
|
|
70
|
+
export interface Cursor<T = Obj.Snapshot> {
|
|
71
|
+
readonly _tag: 'Cursor';
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Retention options for a feed.
|
|
76
|
+
*/
|
|
77
|
+
export interface RetentionOptions {
|
|
78
|
+
/** Retain items after this cursor position. */
|
|
79
|
+
// TODO(wittjosiah): Use FeedCursor from @dxos/feed?
|
|
80
|
+
cursor?: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
//
|
|
84
|
+
// Factory
|
|
85
|
+
//
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Creates a new feed object.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* const feed = Feed.make({ name: 'notifications', kind: 'org.dxos.plugin.notifications.v1' });
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
// TODO(wittjosiah): How to control the feed namespace (data/trace)? Why do feeds have namespaces?
|
|
96
|
+
export const make = (props: Obj.MakeProps<typeof Feed> = {}): Feed => Obj.make(Feed, props);
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Derives the queue DXN from the feed object's DXN.
|
|
100
|
+
* Returns `undefined` when the feed is not stored in a space yet.
|
|
101
|
+
*
|
|
102
|
+
* Used internally by the feed service layer.
|
|
103
|
+
*/
|
|
104
|
+
export const getQueueDxn = (feed: Feed): DXN | undefined => {
|
|
105
|
+
const self = Obj.getDXN(feed).asEchoDXN();
|
|
106
|
+
if (!self || !self.spaceId) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
return new DXN(DXN.kind.QUEUE, [feed.namespace ?? 'data', self.spaceId, self.echoId]);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
//
|
|
113
|
+
// Service
|
|
114
|
+
//
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Effect service for feed operations.
|
|
118
|
+
* Provides the bridge to the underlying storage implementation.
|
|
119
|
+
* Must be provided by the application layer (e.g., echo-db).
|
|
120
|
+
*/
|
|
121
|
+
// TODO(dmaretskyi): Rename to FeedService so it shows up as "FeedService" in the TypeScript hovers instead of just "Service".
|
|
122
|
+
export class Service extends Context.Tag('@dxos/echo/Feed/Service')<
|
|
123
|
+
Service,
|
|
124
|
+
{
|
|
125
|
+
/**
|
|
126
|
+
* Appends items to a feed.
|
|
127
|
+
*/
|
|
128
|
+
append(feed: Feed, items: Entity.Unknown[]): Promise<void>;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Removes items from a feed by ID.
|
|
132
|
+
*/
|
|
133
|
+
// TODO(dmaretskyi): Change type to ObjectId.
|
|
134
|
+
remove(feed: Feed, ids: string[]): Promise<void>;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Queries items in a feed.
|
|
138
|
+
*/
|
|
139
|
+
query: {
|
|
140
|
+
<Q extends Query.Any>(feed: Feed, query: Q): QueryResult.QueryResult<Query.Type<Q>>;
|
|
141
|
+
<F extends Filter.Any>(feed: Feed, filter: F): QueryResult.QueryResult<Filter.Type<F>>;
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
>() {}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Layer that provides a Feed service that throws when accessed.
|
|
148
|
+
* Useful as a default layer when no feed service is available.
|
|
149
|
+
*/
|
|
150
|
+
export const notAvailable: Layer.Layer<Service> = Layer.succeed(Service, {
|
|
151
|
+
append: () => {
|
|
152
|
+
throw new Error('Feed.Service not available');
|
|
153
|
+
},
|
|
154
|
+
remove: () => {
|
|
155
|
+
throw new Error('Feed.Service not available');
|
|
156
|
+
},
|
|
157
|
+
query: () => {
|
|
158
|
+
throw new Error('Feed.Service not available');
|
|
159
|
+
},
|
|
160
|
+
} as Context.Tag.Service<Service>);
|
|
161
|
+
|
|
162
|
+
//
|
|
163
|
+
// Operations
|
|
164
|
+
//
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Appends items to a feed.
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```ts
|
|
171
|
+
* yield* Feed.append(feed, [Obj.make(Notification, { title: 'Hello' })]);
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
export const append = (feed: Feed, items: Entity.Unknown[]): Effect.Effect<void, never, Service> =>
|
|
175
|
+
Effect.gen(function* () {
|
|
176
|
+
const service = yield* Service;
|
|
177
|
+
yield* Effect.promise(() => service.append(feed, items));
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Removes items from a feed.
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```ts
|
|
185
|
+
* yield* Feed.remove(feed, [item]);
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
// TODO(dmaretskyi): Should we allow snapshots here? - what does it mean to remove a snapshot?
|
|
189
|
+
export const remove = (feed: Feed, items: (Entity.Unknown | Obj.Snapshot)[]): Effect.Effect<void, never, Service> =>
|
|
190
|
+
Effect.gen(function* () {
|
|
191
|
+
const service = yield* Service;
|
|
192
|
+
const ids = items.map((item) => item.id);
|
|
193
|
+
yield* Effect.promise(() => service.remove(feed, ids));
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Creates a reactive query over items in a feed.
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```ts
|
|
201
|
+
* const result = yield* Feed.query(feed, Filter.type(Person));
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
// TODO(dmaretskyi): Suport chained queries:
|
|
205
|
+
// const result = yield* feed.pipe(Feed.query(Filter.type(Person))); result.subscribe(...)
|
|
206
|
+
// const objects = yield* feed.pipe(Feed.query(Filter.type(Person))).run;
|
|
207
|
+
// const object = yield* feed.pipe(Feed.query(Filter.type(Person))).first;
|
|
208
|
+
// ... unify for Database and schema queries.
|
|
209
|
+
export const query: {
|
|
210
|
+
<Q extends Query.Any>(feed: Feed, query: Q): Effect.Effect<QueryResult.QueryResult<Query.Type<Q>>, never, Service>;
|
|
211
|
+
<F extends Filter.Any>(feed: Feed, filter: F): Effect.Effect<QueryResult.QueryResult<Filter.Type<F>>, never, Service>;
|
|
212
|
+
} = (feed: Feed, queryOrFilter: Query.Any | Filter.Any) =>
|
|
213
|
+
Service.pipe(Effect.map((service) => service.query(feed, queryOrFilter as any) as QueryResult.QueryResult<any>));
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Executes a feed query once and returns the results.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```ts
|
|
220
|
+
* const items = yield* Feed.runQuery(feed, Filter.type(Person));
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
export const runQuery: {
|
|
224
|
+
<Q extends Query.Any>(feed: Feed, query: Q): Effect.Effect<Query.Type<Q>[], never, Service>;
|
|
225
|
+
<F extends Filter.Any>(feed: Feed, filter: F): Effect.Effect<Filter.Type<F>[], never, Service>;
|
|
226
|
+
} = (feed: Feed, queryOrFilter: Query.Any | Filter.Any) =>
|
|
227
|
+
query(feed, queryOrFilter as any).pipe(Effect.flatMap((queryResult) => Effect.promise(() => queryResult.run())));
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Creates a cursor for iterating over feed items.
|
|
231
|
+
* Currently stubbed — cursor operations are not yet implemented.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* const cursor = yield* Feed.cursor<Person>(feed);
|
|
236
|
+
* const item = yield* Feed.next(cursor);
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
// TODO(wittjosiah): Implement cursor operations. Use Effect streams?
|
|
240
|
+
export const cursor = <T = Obj.Snapshot>(_feed: Feed): Effect.Effect<Cursor<T>, never, Service> =>
|
|
241
|
+
Effect.succeed({ _tag: 'Cursor' } as Cursor<T>);
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Returns the next item from a feed cursor.
|
|
245
|
+
* Currently stubbed — cursor operations are not yet implemented.
|
|
246
|
+
*/
|
|
247
|
+
export const next = <T = Obj.Snapshot>(_cursor: Cursor<T>): Effect.Effect<T, never, Service> =>
|
|
248
|
+
Effect.die('Feed.next is not yet implemented');
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Returns the next item from a feed cursor as an Option.
|
|
252
|
+
* Currently stubbed — cursor operations are not yet implemented.
|
|
253
|
+
*/
|
|
254
|
+
export const nextOption = <T = Obj.Snapshot>(_cursor: Cursor<T>): Effect.Effect<Option.Option<T>, never, Service> =>
|
|
255
|
+
Effect.die('Feed.nextOption is not yet implemented');
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Sets the local retention policy for a feed.
|
|
259
|
+
* Currently stubbed — queues do not yet support retention.
|
|
260
|
+
*
|
|
261
|
+
* @example
|
|
262
|
+
* ```ts
|
|
263
|
+
* yield* Feed.setRetention(feed, { count: 1000 });
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
// TODO(feed): Implement when queue retention is supported.
|
|
267
|
+
export const setRetention = (_feed: Feed, _options: RetentionOptions): Effect.Effect<void, never, Service> =>
|
|
268
|
+
Effect.void;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import * as Filter from './Filter';
|
|
8
|
+
|
|
9
|
+
describe('Filter timestamp builders', () => {
|
|
10
|
+
test('updated({ after }) produces correct AST', () => {
|
|
11
|
+
const ts = 1700000000000;
|
|
12
|
+
const f = Filter.updated({ after: ts });
|
|
13
|
+
expect(f.ast).toEqual({ type: 'timestamp', field: 'updatedAt', operator: 'gte', value: ts });
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('updated({ before }) produces correct AST', () => {
|
|
17
|
+
const ts = 1700000000000;
|
|
18
|
+
const f = Filter.updated({ before: ts });
|
|
19
|
+
expect(f.ast).toEqual({ type: 'timestamp', field: 'updatedAt', operator: 'lte', value: ts });
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('created({ after }) produces correct AST', () => {
|
|
23
|
+
const ts = 1700000000000;
|
|
24
|
+
const f = Filter.created({ after: ts });
|
|
25
|
+
expect(f.ast).toEqual({ type: 'timestamp', field: 'createdAt', operator: 'gte', value: ts });
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('created({ before }) produces correct AST', () => {
|
|
29
|
+
const ts = 1700000000000;
|
|
30
|
+
const f = Filter.created({ before: ts });
|
|
31
|
+
expect(f.ast).toEqual({ type: 'timestamp', field: 'createdAt', operator: 'lte', value: ts });
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('updated() accepts Date objects', () => {
|
|
35
|
+
const date = new Date('2026-03-20T21:00:00Z');
|
|
36
|
+
const f = Filter.updated({ after: date });
|
|
37
|
+
expect(f.ast).toEqual({ type: 'timestamp', field: 'updatedAt', operator: 'gte', value: date.getTime() });
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('created() accepts Date objects', () => {
|
|
41
|
+
const date = new Date('2026-03-20T09:00:00Z');
|
|
42
|
+
const f = Filter.created({ before: date });
|
|
43
|
+
expect(f.ast).toEqual({ type: 'timestamp', field: 'createdAt', operator: 'lte', value: date.getTime() });
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('updated({ after, before }) produces AND of two timestamp nodes', () => {
|
|
47
|
+
const from = 1700000000000;
|
|
48
|
+
const to = 1700086400000;
|
|
49
|
+
const f = Filter.updated({ after: from, before: to });
|
|
50
|
+
expect(f.ast).toEqual({
|
|
51
|
+
type: 'and',
|
|
52
|
+
filters: [
|
|
53
|
+
{ type: 'timestamp', field: 'updatedAt', operator: 'gte', value: from },
|
|
54
|
+
{ type: 'timestamp', field: 'updatedAt', operator: 'lte', value: to },
|
|
55
|
+
],
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('updated({ after, before }) accepts Date objects', () => {
|
|
60
|
+
const from = new Date('2026-03-19T00:00:00Z');
|
|
61
|
+
const to = new Date('2026-03-20T00:00:00Z');
|
|
62
|
+
const f = Filter.updated({ after: from, before: to });
|
|
63
|
+
expect(f.ast).toEqual({
|
|
64
|
+
type: 'and',
|
|
65
|
+
filters: [
|
|
66
|
+
{ type: 'timestamp', field: 'updatedAt', operator: 'gte', value: from.getTime() },
|
|
67
|
+
{ type: 'timestamp', field: 'updatedAt', operator: 'lte', value: to.getTime() },
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('timestamp filters compose with and()', () => {
|
|
73
|
+
const typeFilter = Filter.everything();
|
|
74
|
+
const timeFilter = Filter.updated({ after: 1700000000000 });
|
|
75
|
+
const combined = Filter.and(typeFilter, timeFilter);
|
|
76
|
+
expect(combined.ast.type).toBe('and');
|
|
77
|
+
expect((combined.ast as any).filters).toHaveLength(2);
|
|
78
|
+
expect((combined.ast as any).filters[1]).toEqual({
|
|
79
|
+
type: 'timestamp',
|
|
80
|
+
field: 'updatedAt',
|
|
81
|
+
operator: 'gte',
|
|
82
|
+
value: 1700000000000,
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('timestamp filters pass the is() check', () => {
|
|
87
|
+
const f = Filter.updated({ after: Date.now() });
|
|
88
|
+
expect(Filter.is(f)).toBe(true);
|
|
89
|
+
});
|
|
90
|
+
});
|
package/src/Filter.ts
CHANGED
|
@@ -2,20 +2,23 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
// @import-as-namespace
|
|
6
|
+
|
|
5
7
|
import * as Match from 'effect/Match';
|
|
6
8
|
import * as Schema from 'effect/Schema';
|
|
9
|
+
import * as SchemaAST from 'effect/SchemaAST';
|
|
7
10
|
import type * as Types from 'effect/Types';
|
|
8
11
|
|
|
9
12
|
import { type ForeignKey, type QueryAST } from '@dxos/echo-protocol';
|
|
10
13
|
import { assertArgument } from '@dxos/invariant';
|
|
11
14
|
import { DXN, ObjectId } from '@dxos/keys';
|
|
12
15
|
|
|
13
|
-
import
|
|
16
|
+
import * as internal from './internal';
|
|
14
17
|
import * as Ref from './Ref';
|
|
15
18
|
|
|
16
19
|
export interface Filter<T> {
|
|
17
20
|
// TODO(dmaretskyi): See new effect-schema approach to variance.
|
|
18
|
-
'~Filter': { value: Types.
|
|
21
|
+
'~Filter': { value: Types.Covariant<T> };
|
|
19
22
|
|
|
20
23
|
ast: QueryAST.Filter;
|
|
21
24
|
}
|
|
@@ -30,7 +33,7 @@ export type Any = Filter<any>;
|
|
|
30
33
|
export type Type<F extends Any> = F extends Filter<infer T> ? T : never;
|
|
31
34
|
|
|
32
35
|
class FilterClass implements Any {
|
|
33
|
-
private static variance: Any['~Filter'] = {} as Any['~Filter'];
|
|
36
|
+
private static 'variance': Any['~Filter'] = {} as Any['~Filter'];
|
|
34
37
|
|
|
35
38
|
constructor(public readonly ast: QueryAST.Filter) {}
|
|
36
39
|
|
|
@@ -101,7 +104,19 @@ export const type = <S extends Schema.Schema.All>(
|
|
|
101
104
|
schema: S | string,
|
|
102
105
|
props?: Props<Schema.Schema.Type<S>>,
|
|
103
106
|
): Filter<Schema.Schema.Type<S>> => {
|
|
104
|
-
|
|
107
|
+
if (Schema.isSchema(schema) && SchemaAST.isUnion(schema.ast)) {
|
|
108
|
+
const typenames = schema.ast.types.map((type) => internal.getTypeDXNFromSpecifier(Schema.make(type)));
|
|
109
|
+
return new FilterClass({
|
|
110
|
+
type: 'or',
|
|
111
|
+
filters: typenames.map((typename) => ({
|
|
112
|
+
type: 'object',
|
|
113
|
+
typename: typename.toString(),
|
|
114
|
+
props: {},
|
|
115
|
+
})),
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const dxn = internal.getTypeDXNFromSpecifier(schema);
|
|
105
120
|
return new FilterClass({
|
|
106
121
|
type: 'object',
|
|
107
122
|
typename: dxn.toString(),
|
|
@@ -180,7 +195,7 @@ export const foreignKeys = <S extends Schema.Schema.All>(
|
|
|
180
195
|
schema: S | string,
|
|
181
196
|
keys: ForeignKey[],
|
|
182
197
|
): Filter<Schema.Schema.Type<S>> => {
|
|
183
|
-
const dxn = getTypeDXNFromSpecifier(schema);
|
|
198
|
+
const dxn = internal.getTypeDXNFromSpecifier(schema);
|
|
184
199
|
return new FilterClass({
|
|
185
200
|
type: 'object',
|
|
186
201
|
typename: dxn.toString(),
|
|
@@ -263,7 +278,7 @@ export const lte = <T>(value: T): Filter<T | undefined> => {
|
|
|
263
278
|
* Predicate for property to be in the provided array.
|
|
264
279
|
* @param values - Values to check against.
|
|
265
280
|
*/
|
|
266
|
-
const in$ = <T>(...values: T[]): Filter<T
|
|
281
|
+
const in$ = <T>(...values: T[]): Filter<T> => {
|
|
267
282
|
return new FilterClass({
|
|
268
283
|
type: 'in',
|
|
269
284
|
values,
|
|
@@ -287,7 +302,7 @@ export const contains = <T>(value: T): Filter<readonly T[] | undefined> => {
|
|
|
287
302
|
* @param from - Start of the range (inclusive).
|
|
288
303
|
* @param to - End of the range (exclusive).
|
|
289
304
|
*/
|
|
290
|
-
export const between = <T>(from: T, to: T): Filter<
|
|
305
|
+
export const between = <T>(from: T, to: T): Filter<T> => {
|
|
291
306
|
return new FilterClass({
|
|
292
307
|
type: 'range',
|
|
293
308
|
from,
|
|
@@ -295,6 +310,34 @@ export const between = <T>(from: T, to: T): Filter<unknown> => {
|
|
|
295
310
|
});
|
|
296
311
|
};
|
|
297
312
|
|
|
313
|
+
type TimeRange = { after?: Date | number; before?: Date | number };
|
|
314
|
+
|
|
315
|
+
const _toUnixMs = (date: Date | number): number => (typeof date === 'number' ? date : date.getTime());
|
|
316
|
+
|
|
317
|
+
const _timeRangeFilter = (field: 'updatedAt' | 'createdAt', range: TimeRange): Any => {
|
|
318
|
+
const filters: Any[] = [];
|
|
319
|
+
if (range.after != null) {
|
|
320
|
+
filters.push(new FilterClass({ type: 'timestamp', field, operator: 'gte', value: _toUnixMs(range.after) }));
|
|
321
|
+
}
|
|
322
|
+
if (range.before != null) {
|
|
323
|
+
filters.push(new FilterClass({ type: 'timestamp', field, operator: 'lte', value: _toUnixMs(range.before) }));
|
|
324
|
+
}
|
|
325
|
+
if (filters.length === 0) {
|
|
326
|
+
return everything();
|
|
327
|
+
}
|
|
328
|
+
return filters.length === 1 ? filters[0] : and(...filters);
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Filter objects by updatedAt timestamp.
|
|
333
|
+
*/
|
|
334
|
+
export const updated = (range: TimeRange): Any => _timeRangeFilter('updatedAt', range);
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Filter objects by createdAt timestamp.
|
|
338
|
+
*/
|
|
339
|
+
export const created = (range: TimeRange): Any => _timeRangeFilter('createdAt', range);
|
|
340
|
+
|
|
298
341
|
/**
|
|
299
342
|
* Negate the filter.
|
|
300
343
|
*/
|
|
@@ -374,3 +417,8 @@ const processPredicate = (predicate: any): QueryAST.Filter => {
|
|
|
374
417
|
Match.orElse((value) => eq(value).ast),
|
|
375
418
|
);
|
|
376
419
|
};
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Returns a human-readable string representation of a Filter AST.
|
|
423
|
+
*/
|
|
424
|
+
export const pretty = (filter: Any): string => internal.prettyFilter(filter.ast);
|
package/src/Format.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import type * as internal from './internal';
|
|
6
6
|
|
|
7
|
-
export * from './internal/
|
|
7
|
+
export * from './internal/Format';
|
|
8
8
|
|
|
9
|
-
export type
|
|
9
|
+
export type Format = internal.TypeFormat;
|
package/src/Hypergraph.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { type DXN } from '@dxos/keys';
|
|
|
6
6
|
|
|
7
7
|
import type * as Database from './Database';
|
|
8
8
|
import type * as Entity from './Entity';
|
|
9
|
-
import
|
|
9
|
+
import type * as internal from './internal';
|
|
10
10
|
import type * as Key from './Key';
|
|
11
11
|
import type * as Ref from './Ref';
|
|
12
12
|
import type * as SchemaRegistry from './SchemaRegistry';
|
|
@@ -39,13 +39,12 @@ export interface RefResolverOptions {
|
|
|
39
39
|
* Middleware to change the resolved object before returning it.
|
|
40
40
|
* @deprecated On track to be removed.
|
|
41
41
|
*/
|
|
42
|
-
middleware?: (obj: AnyProperties) => AnyProperties;
|
|
42
|
+
middleware?: (obj: internal.AnyProperties) => internal.AnyProperties;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
|
-
*
|
|
46
|
+
* Manages cross-space database interactions.
|
|
47
47
|
*/
|
|
48
|
-
// TODO(burdon): Comment required.
|
|
49
48
|
export interface Hypergraph extends Database.Queryable {
|
|
50
49
|
get schemaRegistry(): SchemaRegistry.SchemaRegistry;
|
|
51
50
|
|
|
@@ -71,4 +70,10 @@ export interface Hypergraph extends Database.Queryable {
|
|
|
71
70
|
*/
|
|
72
71
|
// TODO(dmaretskyi): Restructure API: Remove middleware.
|
|
73
72
|
createRefResolver(options: RefResolverOptions): Ref.Resolver;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get a database by space ID.
|
|
76
|
+
* @returns The database for the given space ID, or undefined if not found.
|
|
77
|
+
*/
|
|
78
|
+
getDatabase(spaceId: Key.SpaceId): Database.Database | undefined;
|
|
74
79
|
}
|
package/src/JsonSchema.ts
CHANGED
|
@@ -2,15 +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
|
|
9
|
+
import * as jsonSchemaInternal from './internal/JsonSchema';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Decode JSON Schema to Effect Schema.
|
|
13
|
+
*/
|
|
14
|
+
export const toEffectSchema = jsonSchemaInternal.toEffectSchema;
|
|
8
15
|
|
|
9
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Encode Effect Schema to JSON Schema.
|
|
18
|
+
*/
|
|
19
|
+
export const toJsonSchema = jsonSchemaInternal.toJsonSchema;
|
|
10
20
|
|
|
11
21
|
/**
|
|
12
22
|
* Serializable JsonSchema type definition.
|
|
13
23
|
*/
|
|
14
|
-
export type JsonSchema = JsonSchemaType;
|
|
24
|
+
export type JsonSchema = jsonSchemaInternal.JsonSchemaType;
|
|
15
25
|
|
|
16
|
-
export const JsonSchema: Schema.Schema<JsonSchemaType> = JsonSchemaType;
|
|
26
|
+
export const JsonSchema: Schema.Schema<jsonSchemaInternal.JsonSchemaType> = jsonSchemaInternal.JsonSchemaType;
|
package/src/Obj.test.ts
CHANGED
|
@@ -8,6 +8,7 @@ import * as Entity from './Entity';
|
|
|
8
8
|
import { SnapshotKindId } from './internal';
|
|
9
9
|
import * as Obj from './Obj';
|
|
10
10
|
import * as Ref from './Ref';
|
|
11
|
+
import * as Relation from './Relation';
|
|
11
12
|
import { TestSchema } from './testing';
|
|
12
13
|
|
|
13
14
|
describe('Obj', () => {
|
|
@@ -19,6 +20,10 @@ describe('Obj', () => {
|
|
|
19
20
|
// Snapshot has SnapshotKindId, not KindId.
|
|
20
21
|
expect(snapshot[SnapshotKindId]).toBe(Entity.Kind.Object);
|
|
21
22
|
expect((snapshot as any)[Entity.KindId]).toBeUndefined();
|
|
23
|
+
expect(Obj.isSnapshot(snapshot)).toBe(true);
|
|
24
|
+
expect(Relation.isSnapshot(snapshot)).toBe(false);
|
|
25
|
+
expect(Entity.isEntity(snapshot)).toBe(false);
|
|
26
|
+
expect(Entity.isSnapshot(snapshot)).toBe(true);
|
|
22
27
|
|
|
23
28
|
// Snapshot has same id and properties.
|
|
24
29
|
expect(snapshot.id).toBe(obj.id);
|
|
@@ -41,8 +46,8 @@ describe('Obj', () => {
|
|
|
41
46
|
expect(Obj.getDXN(snapshot)).toBeDefined();
|
|
42
47
|
|
|
43
48
|
// getTypename - works with both.
|
|
44
|
-
expect(Obj.getTypename(obj)).toBe('example.
|
|
45
|
-
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');
|
|
46
51
|
|
|
47
52
|
// getMeta - works with both.
|
|
48
53
|
expect(Obj.getMeta(obj)).toBeDefined();
|
|
@@ -77,6 +82,62 @@ describe('Obj', () => {
|
|
|
77
82
|
});
|
|
78
83
|
});
|
|
79
84
|
|
|
85
|
+
describe('snapshotOf', () => {
|
|
86
|
+
test('returns true for snapshot of matching schema', ({ expect }) => {
|
|
87
|
+
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
88
|
+
const snapshot = Obj.getSnapshot(obj);
|
|
89
|
+
|
|
90
|
+
expect(Obj.snapshotOf(TestSchema.Person, snapshot)).toBe(true);
|
|
91
|
+
expect(Obj.snapshotOf(TestSchema.Organization, snapshot)).toBe(false);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test('returns false for reactive object', ({ expect }) => {
|
|
95
|
+
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
96
|
+
|
|
97
|
+
expect(Obj.snapshotOf(TestSchema.Person, obj)).toBe(false);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('returns false for plain object with matching shape', ({ expect }) => {
|
|
101
|
+
const plain = { id: 'test', name: 'Test' };
|
|
102
|
+
|
|
103
|
+
expect(Obj.snapshotOf(TestSchema.Person, plain)).toBe(false);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test('curried form works', ({ expect }) => {
|
|
107
|
+
const snapshot = Obj.getSnapshot(Obj.make(TestSchema.Person, { name: 'Test' }));
|
|
108
|
+
const isPersonSnapshot = Obj.snapshotOf(TestSchema.Person);
|
|
109
|
+
|
|
110
|
+
expect(isPersonSnapshot(snapshot)).toBe(true);
|
|
111
|
+
expect(isPersonSnapshot({})).toBe(false);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('getKeys', () => {
|
|
116
|
+
const SOURCE = 'test-source';
|
|
117
|
+
|
|
118
|
+
test('returns keys from reactive object and snapshot', ({ expect }) => {
|
|
119
|
+
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
120
|
+
Obj.change(obj, (obj) => {
|
|
121
|
+
const meta = Obj.getMeta(obj);
|
|
122
|
+
meta.keys.push({ source: SOURCE, id: 'key-1' });
|
|
123
|
+
meta.keys.push({ source: SOURCE, id: 'key-2' });
|
|
124
|
+
meta.keys.push({ source: 'other', id: 'key-3' });
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
expect(Obj.getKeys(obj, SOURCE)).toHaveLength(2);
|
|
128
|
+
expect(Obj.getKeys(obj, SOURCE).map((k) => k.id)).toEqual(['key-1', 'key-2']);
|
|
129
|
+
|
|
130
|
+
const snapshot = Obj.getSnapshot(obj);
|
|
131
|
+
expect(Obj.getKeys(snapshot, SOURCE)).toHaveLength(2);
|
|
132
|
+
expect(Obj.getKeys(snapshot, SOURCE).map((k) => k.id)).toEqual(['key-1', 'key-2']);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test('throws for plain object without metadata', ({ expect }) => {
|
|
136
|
+
const plain = { id: 'plain-1', name: 'Plain' };
|
|
137
|
+
expect(() => Obj.getKeys(plain as any, SOURCE)).toThrow(/ObjectMeta not found/);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
80
141
|
describe('clone', () => {
|
|
81
142
|
test('clones object with same properties', ({ expect }) => {
|
|
82
143
|
const original = Obj.make(TestSchema.Person, {
|
|
@@ -105,8 +166,8 @@ describe('Obj', () => {
|
|
|
105
166
|
|
|
106
167
|
const cloned = Obj.clone(original);
|
|
107
168
|
|
|
108
|
-
Obj.change(original, (
|
|
109
|
-
|
|
169
|
+
Obj.change(original, (obj) => {
|
|
170
|
+
obj.name = 'Bob';
|
|
110
171
|
});
|
|
111
172
|
|
|
112
173
|
expect(original.name).toBe('Bob');
|
|
@@ -272,8 +333,8 @@ describe('Obj', () => {
|
|
|
272
333
|
expect(cloned.address?.coordinates.lng).toBe(-122.4194);
|
|
273
334
|
|
|
274
335
|
// Modifying nested properties should be independent
|
|
275
|
-
Obj.change(person, (
|
|
276
|
-
|
|
336
|
+
Obj.change(person, (obj) => {
|
|
337
|
+
obj.address!.city = 'New York';
|
|
277
338
|
});
|
|
278
339
|
|
|
279
340
|
expect(cloned.address?.city).toBe('San Francisco');
|
|
@@ -305,8 +366,8 @@ describe('Obj', () => {
|
|
|
305
366
|
expect(cloned.tasks?.[2]?.target).not.toBe(task3);
|
|
306
367
|
|
|
307
368
|
// Modifying original tasks should not affect cloned ones
|
|
308
|
-
Obj.change(task1, (
|
|
309
|
-
|
|
369
|
+
Obj.change(task1, (obj) => {
|
|
370
|
+
obj.title = 'Updated Task 1';
|
|
310
371
|
});
|
|
311
372
|
|
|
312
373
|
expect(cloned.tasks?.[0]?.target?.title).toBe('Task 1');
|