@dxos/echo 0.8.4-staging.ac66bdf99f → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +102 -5
- package/README.md +7 -7
- package/dist/lib/neutral/Annotation.mjs +37 -6
- package/dist/lib/neutral/Database.mjs +6 -17
- package/dist/lib/neutral/Entity.mjs +31 -20
- package/dist/lib/neutral/Err.mjs +3 -3
- package/dist/lib/neutral/Feed.mjs +23 -19
- package/dist/lib/neutral/Filter.mjs +13 -15
- package/dist/lib/neutral/Format.mjs +23 -3
- package/dist/lib/neutral/JsonSchema.mjs +7 -8
- package/dist/lib/neutral/Key.mjs +9 -5
- package/dist/lib/neutral/Migration.mjs +11 -10
- package/dist/lib/neutral/Obj.mjs +29 -20
- package/dist/lib/neutral/Order.mjs +7 -3
- package/dist/lib/neutral/Query.mjs +17 -17
- package/dist/lib/neutral/QueryResult.mjs +1 -1
- package/dist/lib/neutral/Ref.mjs +10 -9
- package/dist/lib/neutral/Registry.mjs +14 -0
- package/dist/lib/neutral/Relation.mjs +28 -25
- package/dist/lib/neutral/Scope.mjs +12 -0
- package/dist/lib/neutral/Tag.mjs +17 -14
- package/dist/lib/neutral/Type.mjs +54 -26
- package/dist/lib/neutral/{chunk-OMUPQMLR.mjs → chunk-35INCYOE.mjs} +1 -1
- package/dist/lib/neutral/chunk-35INCYOE.mjs.map +7 -0
- package/dist/lib/neutral/chunk-3PBP4V4O.mjs +101 -0
- package/dist/lib/neutral/chunk-3PBP4V4O.mjs.map +7 -0
- package/dist/lib/neutral/chunk-4ZUHOTCG.mjs +184 -0
- package/dist/lib/neutral/chunk-4ZUHOTCG.mjs.map +7 -0
- package/dist/lib/neutral/chunk-5SMDBFVB.mjs +108 -0
- package/dist/lib/neutral/chunk-5SMDBFVB.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-OS35K56T.mjs → chunk-5SUJPHAE.mjs} +3 -3
- package/dist/lib/neutral/{chunk-OS35K56T.mjs.map → chunk-5SUJPHAE.mjs.map} +2 -2
- package/dist/lib/neutral/{chunk-GZQTCRJB.mjs → chunk-6M2Z6WBH.mjs} +22 -2
- package/dist/lib/neutral/chunk-6M2Z6WBH.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-V36VO5SS.mjs → chunk-6YDI3J37.mjs} +32 -40
- package/dist/lib/neutral/chunk-6YDI3J37.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-MOR5ERFM.mjs → chunk-7FPIAJIV.mjs} +701 -1256
- package/dist/lib/neutral/chunk-7FPIAJIV.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-ANHVGJI4.mjs → chunk-7LOUAPYZ.mjs} +9 -5
- package/dist/lib/neutral/chunk-7LOUAPYZ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-JUXPFOEI.mjs → chunk-7PI7C4EF.mjs} +48 -88
- package/dist/lib/neutral/chunk-7PI7C4EF.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-UBEZSGXY.mjs → chunk-BBFJWWAV.mjs} +6 -6
- package/dist/lib/neutral/chunk-BBFJWWAV.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-UI6MWK5W.mjs → chunk-EVK6XBXO.mjs} +16 -2
- package/dist/lib/neutral/chunk-EVK6XBXO.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-7RO7CPBZ.mjs → chunk-IGK6FN65.mjs} +2 -2
- package/dist/lib/neutral/{chunk-HBUZJNZO.mjs → chunk-LWXVKPPW.mjs} +94 -99
- package/dist/lib/neutral/chunk-LWXVKPPW.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-BVOFLCVF.mjs → chunk-MZ7K3MLL.mjs} +9 -6
- package/dist/lib/neutral/chunk-MZ7K3MLL.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-TBKX6JQO.mjs → chunk-O6BH7EPN.mjs} +30 -3
- package/dist/lib/neutral/chunk-O6BH7EPN.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-EAMSSLZC.mjs → chunk-QQIYS74I.mjs} +83 -46
- package/dist/lib/neutral/chunk-QQIYS74I.mjs.map +7 -0
- package/dist/lib/neutral/chunk-R5W6DXR4.mjs +678 -0
- package/dist/lib/neutral/chunk-R5W6DXR4.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-WAK4DMFV.mjs → chunk-RIVWNMSF.mjs} +12 -7
- package/dist/lib/neutral/chunk-RIVWNMSF.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-T6W2LEZU.mjs → chunk-SBVFRTST.mjs} +73 -38
- package/dist/lib/neutral/chunk-SBVFRTST.mjs.map +7 -0
- package/dist/lib/neutral/chunk-T6E37YIP.mjs +251 -0
- package/dist/lib/neutral/chunk-T6E37YIP.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-DQYLD2RB.mjs → chunk-TFEWTY5A.mjs} +155 -129
- package/dist/lib/neutral/chunk-TFEWTY5A.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-B4BASU6W.mjs → chunk-TYGKCRMK.mjs} +85 -76
- package/dist/lib/neutral/chunk-TYGKCRMK.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-4OIBYSXE.mjs → chunk-UUP46KUQ.mjs} +78 -32
- package/dist/lib/neutral/chunk-UUP46KUQ.mjs.map +7 -0
- package/dist/lib/neutral/chunk-WISOH2XH.mjs +36 -0
- package/dist/lib/neutral/chunk-WISOH2XH.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-G3IQMKF7.mjs → chunk-WTQJHC75.mjs} +111 -112
- package/dist/lib/neutral/chunk-WTQJHC75.mjs.map +7 -0
- package/dist/lib/neutral/chunk-WU3GIANS.mjs +31 -0
- package/dist/lib/neutral/chunk-WU3GIANS.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-TU3GW67D.mjs → chunk-ZGNNFYHS.mjs} +40 -40
- package/dist/lib/neutral/chunk-ZGNNFYHS.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +47 -41
- package/dist/lib/neutral/internal/index.mjs +137 -72
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/testing/index.mjs +261 -178
- package/dist/lib/neutral/testing/index.mjs.map +4 -4
- package/dist/types/src/Annotation.d.ts +108 -4
- package/dist/types/src/Annotation.d.ts.map +1 -1
- package/dist/types/src/Annotation.test.d.ts +2 -0
- package/dist/types/src/Annotation.test.d.ts.map +1 -0
- package/dist/types/src/Collection.d.ts +2 -3
- package/dist/types/src/Collection.d.ts.map +1 -1
- package/dist/types/src/Database.d.ts +56 -49
- package/dist/types/src/Database.d.ts.map +1 -1
- package/dist/types/src/Dataset.d.ts +16 -6
- package/dist/types/src/Dataset.d.ts.map +1 -1
- package/dist/types/src/Entity.d.ts +101 -28
- package/dist/types/src/Entity.d.ts.map +1 -1
- package/dist/types/src/Err.d.ts +27 -27
- package/dist/types/src/Err.d.ts.map +1 -1
- package/dist/types/src/Feed.d.ts +66 -19
- package/dist/types/src/Feed.d.ts.map +1 -1
- package/dist/types/src/Filter.d.ts +38 -12
- package/dist/types/src/Filter.d.ts.map +1 -1
- package/dist/types/src/Format.d.ts +0 -2
- package/dist/types/src/Format.d.ts.map +1 -1
- package/dist/types/src/Hypergraph.d.ts +14 -9
- package/dist/types/src/Hypergraph.d.ts.map +1 -1
- package/dist/types/src/Json.d.ts +33 -0
- package/dist/types/src/Json.d.ts.map +1 -0
- package/dist/types/src/Json.test.d.ts +2 -0
- package/dist/types/src/Json.test.d.ts.map +1 -0
- package/dist/types/src/JsonSchema.d.ts +2 -2
- package/dist/types/src/JsonSchema.d.ts.map +1 -1
- package/dist/types/src/Key.d.ts +1 -1
- package/dist/types/src/Key.d.ts.map +1 -1
- package/dist/types/src/Migration.d.ts +26 -11
- package/dist/types/src/Migration.d.ts.map +1 -1
- package/dist/types/src/Obj.d.ts +104 -61
- package/dist/types/src/Obj.d.ts.map +1 -1
- package/dist/types/src/Order.d.ts +10 -0
- package/dist/types/src/Order.d.ts.map +1 -1
- package/dist/types/src/Query.d.ts +34 -12
- package/dist/types/src/Query.d.ts.map +1 -1
- package/dist/types/src/QueryResult.d.ts +21 -0
- package/dist/types/src/QueryResult.d.ts.map +1 -1
- package/dist/types/src/Ref.d.ts +15 -7
- package/dist/types/src/Ref.d.ts.map +1 -1
- package/dist/types/src/Registry.d.ts +131 -0
- package/dist/types/src/Registry.d.ts.map +1 -0
- package/dist/types/src/Relation.d.ts +73 -41
- package/dist/types/src/Relation.d.ts.map +1 -1
- package/dist/types/src/Scope.d.ts +35 -0
- package/dist/types/src/Scope.d.ts.map +1 -0
- package/dist/types/src/Tag.d.ts +21 -5
- package/dist/types/src/Tag.d.ts.map +1 -1
- package/dist/types/src/Type.d.ts +362 -95
- package/dist/types/src/Type.d.ts.map +1 -1
- package/dist/types/src/View.d.ts +9 -12
- package/dist/types/src/View.d.ts.map +1 -1
- package/dist/types/src/exemplars.test.d.ts +2 -0
- package/dist/types/src/exemplars.test.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +4 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/annotations.d.ts +79 -38
- package/dist/types/src/internal/Annotation/annotations.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/dictionary.d.ts +24 -0
- package/dist/types/src/internal/Annotation/dictionary.d.ts.map +1 -0
- package/dist/types/src/internal/Annotation/entity-dictionary.d.ts +14 -0
- package/dist/types/src/internal/Annotation/entity-dictionary.d.ts.map +1 -0
- package/dist/types/src/internal/Annotation/index.d.ts +4 -2
- package/dist/types/src/internal/Annotation/index.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/sorting.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/util.d.ts +14 -5
- package/dist/types/src/internal/Annotation/util.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/api.d.ts +17 -3
- package/dist/types/src/internal/Entity/api.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/entity.d.ts +72 -8
- package/dist/types/src/internal/Entity/entity.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/guard.d.ts +10 -0
- package/dist/types/src/internal/Entity/guard.d.ts.map +1 -0
- package/dist/types/src/internal/Entity/index.d.ts +2 -0
- package/dist/types/src/internal/Entity/index.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/model.d.ts +21 -17
- package/dist/types/src/internal/Entity/model.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/object.d.ts +3 -3
- package/dist/types/src/internal/Entity/object.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/relation.d.ts +30 -7
- package/dist/types/src/internal/Entity/relation.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/type-kind.d.ts +24 -0
- package/dist/types/src/internal/Entity/type-kind.d.ts.map +1 -0
- package/dist/types/src/internal/Entity/type-uri.d.ts +24 -0
- package/dist/types/src/internal/Entity/type-uri.d.ts.map +1 -0
- package/dist/types/src/internal/Entity/version.d.ts.map +1 -1
- package/dist/types/src/internal/Format/date.d.ts.map +1 -1
- package/dist/types/src/internal/Format/format.d.ts +3 -2
- package/dist/types/src/internal/Format/format.d.ts.map +1 -1
- package/dist/types/src/internal/Format/index.d.ts +2 -2
- package/dist/types/src/internal/Format/index.d.ts.map +1 -1
- package/dist/types/src/internal/Format/number.d.ts.map +1 -1
- package/dist/types/src/internal/Format/object.d.ts +3 -1
- package/dist/types/src/internal/Format/object.d.ts.map +1 -1
- package/dist/types/src/internal/Format/types.d.ts.map +1 -1
- package/dist/types/src/internal/JsonSchema/json-schema-normalize.d.ts.map +1 -1
- package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts +34 -34
- package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts.map +1 -1
- package/dist/types/src/internal/JsonSchema/json-schema.d.ts +3 -2
- package/dist/types/src/internal/JsonSchema/json-schema.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/atoms.d.ts +38 -0
- package/dist/types/src/internal/Obj/atoms.d.ts.map +1 -0
- package/dist/types/src/internal/Obj/clone.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/common.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/create-object.d.ts +12 -12
- package/dist/types/src/internal/Obj/create-object.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/deleted.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/index.d.ts +1 -1
- package/dist/types/src/internal/Obj/index.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/json-serializer.d.ts +8 -8
- package/dist/types/src/internal/Obj/json-serializer.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/set-value.d.ts +1 -1
- package/dist/types/src/internal/Obj/set-value.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/snapshot.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/typed-object.d.ts +1 -1
- package/dist/types/src/internal/Query/index.d.ts +2 -0
- package/dist/types/src/internal/Query/index.d.ts.map +1 -0
- package/dist/types/src/internal/{Query.d.ts → Query/pretty.d.ts} +1 -1
- package/dist/types/src/internal/Query/pretty.d.ts.map +1 -0
- package/dist/types/src/internal/Ref/atoms.d.ts +10 -0
- package/dist/types/src/internal/Ref/atoms.d.ts.map +1 -0
- package/dist/types/src/internal/Ref/ref-array.d.ts +2 -2
- package/dist/types/src/internal/Ref/ref.d.ts +50 -19
- package/dist/types/src/internal/Ref/ref.d.ts.map +1 -1
- package/dist/types/src/internal/Ref/utils.d.ts +8 -0
- package/dist/types/src/internal/Ref/utils.d.ts.map +1 -0
- package/dist/types/src/internal/Type/compose.d.ts.map +1 -1
- package/dist/types/src/internal/Type/index.d.ts +1 -2
- package/dist/types/src/internal/Type/index.d.ts.map +1 -1
- package/dist/types/src/internal/Type/manipulation.d.ts +0 -1
- package/dist/types/src/internal/Type/manipulation.d.ts.map +1 -1
- package/dist/types/src/internal/Type/type-schema.d.ts +52 -0
- package/dist/types/src/internal/Type/type-schema.d.ts.map +1 -0
- package/dist/types/src/internal/common/api/meta.d.ts +14 -11
- package/dist/types/src/internal/common/api/meta.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/change-context.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/change-context.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/define-hidden-property.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/errors.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/errors.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/event-batch.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/json-serializer.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/make-object.d.ts +11 -5
- package/dist/types/src/internal/common/proxy/make-object.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/ownership.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/proxy-utils.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/reactive-array.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/reactive.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/reactive.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/reactive.test.d.ts +2 -0
- package/dist/types/src/internal/common/proxy/reactive.test.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/schema-validator.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/typed-handler.d.ts +18 -2
- package/dist/types/src/internal/common/proxy/typed-handler.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/base.d.ts +4 -4
- package/dist/types/src/internal/common/types/base.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/entity.d.ts +62 -5
- package/dist/types/src/internal/common/types/entity.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/index.d.ts +1 -1
- package/dist/types/src/internal/common/types/index.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/meta.d.ts +33 -12
- package/dist/types/src/internal/common/types/meta.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/model-symbols.d.ts +15 -4
- package/dist/types/src/internal/common/types/model-symbols.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/typename.d.ts +7 -0
- package/dist/types/src/internal/common/types/typename.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/version.d.ts +1 -1
- package/dist/types/src/internal/common/types/well-known-types.d.ts +11 -0
- package/dist/types/src/internal/common/types/well-known-types.d.ts.map +1 -0
- package/dist/types/src/internal/index.d.ts +2 -2
- package/dist/types/src/internal/index.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +1 -0
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/registry.d.ts +9 -0
- package/dist/types/src/testing/registry.d.ts.map +1 -0
- package/dist/types/src/testing/test-data.d.ts +8 -8
- package/dist/types/src/testing/test-data.d.ts.map +1 -1
- package/dist/types/src/testing/test-schema.d.ts +83 -89
- package/dist/types/src/testing/test-schema.d.ts.map +1 -1
- package/dist/types/src/testing/util.d.ts +5 -3
- package/dist/types/src/testing/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +26 -24
- package/src/Annotation.test.ts +439 -0
- package/src/Annotation.ts +158 -4
- package/src/Collection.ts +5 -9
- package/src/Database.ts +93 -100
- package/src/Dataset.ts +10 -2
- package/src/Entity.test.ts +116 -6
- package/src/Entity.ts +134 -32
- package/src/Err.ts +4 -4
- package/src/Feed.ts +92 -44
- package/src/Filter.ts +70 -40
- package/src/Format.ts +0 -4
- package/src/Hypergraph.ts +14 -9
- package/src/Json.test.ts +175 -0
- package/src/Json.ts +103 -0
- package/src/Key.ts +1 -1
- package/src/Migration.ts +39 -19
- package/src/Obj.test.ts +122 -20
- package/src/Obj.ts +168 -91
- package/src/Order.ts +22 -0
- package/src/Query.test.ts +183 -154
- package/src/Query.ts +172 -85
- package/src/QueryResult.ts +26 -0
- package/src/Ref.ts +22 -4
- package/src/Registry.ts +155 -0
- package/src/Relation.test.ts +10 -10
- package/src/Relation.ts +116 -69
- package/src/Scope.ts +50 -0
- package/src/Tag.md +88 -0
- package/src/Tag.ts +49 -6
- package/src/Type.test.ts +223 -18
- package/src/Type.ts +609 -131
- package/src/View.ts +14 -23
- package/src/exemplars.test.ts +21 -0
- package/src/index.ts +4 -4
- package/src/internal/Annotation/annotations.test.ts +31 -11
- package/src/internal/Annotation/annotations.ts +143 -111
- package/src/internal/Annotation/dictionary.ts +47 -0
- package/src/internal/Annotation/entity-dictionary.ts +74 -0
- package/src/internal/Annotation/index.ts +4 -2
- package/src/internal/Annotation/util.ts +17 -8
- package/src/internal/Entity/api.ts +54 -7
- package/src/internal/Entity/entity.ts +196 -47
- package/src/internal/Entity/guard.ts +26 -0
- package/src/internal/Entity/index.ts +2 -0
- package/src/internal/Entity/model.ts +38 -28
- package/src/internal/Entity/object.ts +21 -5
- package/src/internal/Entity/relation.ts +68 -34
- package/src/internal/Entity/type-kind.ts +75 -0
- package/src/internal/Entity/type-uri.ts +92 -0
- package/src/internal/Entity/util.ts +9 -9
- package/src/internal/Format/date.ts +0 -4
- package/src/internal/Format/format.test.ts +21 -0
- package/src/internal/Format/index.ts +2 -3
- package/src/internal/Format/object.ts +21 -4
- package/src/internal/Format/types.ts +1 -1
- package/src/internal/JsonSchema/annotations.ts +1 -1
- package/src/internal/JsonSchema/json-schema-type.ts +4 -4
- package/src/internal/JsonSchema/json-schema.test.ts +71 -145
- package/src/internal/JsonSchema/json-schema.ts +49 -35
- package/src/internal/Obj/atoms.ts +244 -0
- package/src/internal/Obj/clone.ts +9 -4
- package/src/internal/Obj/create-object.test.ts +12 -10
- package/src/internal/Obj/create-object.ts +68 -22
- package/src/internal/Obj/index.ts +1 -1
- package/src/internal/Obj/inspect.ts +5 -3
- package/src/internal/Obj/json-serializer.test.ts +101 -22
- package/src/internal/Obj/json-serializer.ts +89 -33
- package/src/internal/Obj/set-value.test.ts +22 -45
- package/src/internal/Obj/set-value.ts +12 -19
- package/src/internal/Obj/snapshot.ts +13 -4
- package/src/internal/Obj/typed-object.test.ts +9 -11
- package/src/internal/Obj/typed-object.ts +1 -1
- package/src/internal/Query/index.ts +5 -0
- package/src/internal/{Query.ts → Query/pretty.ts} +40 -12
- package/src/internal/Ref/atoms.ts +20 -0
- package/src/internal/Ref/ref-array.ts +3 -3
- package/src/internal/Ref/ref.test.ts +18 -27
- package/src/internal/Ref/ref.ts +137 -59
- package/src/internal/Ref/utils.ts +45 -0
- package/src/internal/Type/compose.test.ts +3 -1
- package/src/internal/Type/index.ts +1 -2
- package/src/internal/Type/manipulation.ts +0 -25
- package/src/internal/Type/type-schema.ts +60 -0
- package/src/internal/common/README.md +2 -2
- package/src/internal/common/api/meta.ts +19 -17
- package/src/internal/common/proxy/change-context.ts +1 -1
- package/src/internal/common/proxy/change.test.ts +91 -83
- package/src/internal/common/proxy/errors.ts +2 -2
- package/src/internal/common/proxy/handler.test.ts +1 -1
- package/src/internal/common/proxy/json-serializer.ts +27 -16
- package/src/internal/common/proxy/make-object.ts +44 -20
- package/src/internal/common/proxy/ownership.ts +2 -2
- package/src/internal/common/proxy/reactive-array.ts +1 -1
- package/src/internal/common/proxy/reactive.test.ts +54 -0
- package/src/internal/common/proxy/reactive.ts +11 -2
- package/src/internal/common/proxy/schema.test.ts +48 -86
- package/src/internal/common/proxy/typed-handler.test.ts +12 -11
- package/src/internal/common/proxy/typed-handler.ts +78 -16
- package/src/internal/common/proxy/typed-object.test.ts +16 -28
- package/src/internal/common/types/base.ts +4 -4
- package/src/internal/common/types/entity.ts +80 -1
- package/src/internal/common/types/index.ts +6 -1
- package/src/internal/common/types/meta.ts +62 -20
- package/src/internal/common/types/model-symbols.ts +24 -4
- package/src/internal/common/types/typename.ts +39 -3
- package/src/internal/common/types/well-known-types.ts +15 -0
- package/src/internal/index.ts +6 -4
- package/src/testing/api.test.ts +15 -9
- package/src/testing/index.ts +1 -0
- package/src/testing/registry.ts +44 -0
- package/src/testing/test-data.ts +159 -99
- package/src/testing/test-schema.ts +22 -58
- package/src/testing/util.ts +14 -11
- package/dist/lib/neutral/Extension.mjs +0 -18
- package/dist/lib/neutral/SchemaRegistry.mjs +0 -2
- package/dist/lib/neutral/chunk-2KHZ36F5.mjs +0 -361
- package/dist/lib/neutral/chunk-2KHZ36F5.mjs.map +0 -7
- package/dist/lib/neutral/chunk-4OIBYSXE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-4P3IXBLT.mjs +0 -45
- package/dist/lib/neutral/chunk-4P3IXBLT.mjs.map +0 -7
- package/dist/lib/neutral/chunk-ANHVGJI4.mjs.map +0 -7
- package/dist/lib/neutral/chunk-B4BASU6W.mjs.map +0 -7
- package/dist/lib/neutral/chunk-BNCCGLJN.mjs +0 -7
- package/dist/lib/neutral/chunk-BNCCGLJN.mjs.map +0 -7
- package/dist/lib/neutral/chunk-BVOFLCVF.mjs.map +0 -7
- package/dist/lib/neutral/chunk-DQYLD2RB.mjs.map +0 -7
- package/dist/lib/neutral/chunk-EAMSSLZC.mjs.map +0 -7
- package/dist/lib/neutral/chunk-G3IQMKF7.mjs.map +0 -7
- package/dist/lib/neutral/chunk-GZQTCRJB.mjs.map +0 -7
- package/dist/lib/neutral/chunk-HBUZJNZO.mjs.map +0 -7
- package/dist/lib/neutral/chunk-JUXPFOEI.mjs.map +0 -7
- package/dist/lib/neutral/chunk-MOR5ERFM.mjs.map +0 -7
- package/dist/lib/neutral/chunk-OMUPQMLR.mjs.map +0 -7
- package/dist/lib/neutral/chunk-PHU22NLC.mjs +0 -136
- package/dist/lib/neutral/chunk-PHU22NLC.mjs.map +0 -7
- package/dist/lib/neutral/chunk-ROG4RXXL.mjs +0 -97
- package/dist/lib/neutral/chunk-ROG4RXXL.mjs.map +0 -7
- package/dist/lib/neutral/chunk-T6W2LEZU.mjs.map +0 -7
- package/dist/lib/neutral/chunk-TBKX6JQO.mjs.map +0 -7
- package/dist/lib/neutral/chunk-TU3GW67D.mjs.map +0 -7
- package/dist/lib/neutral/chunk-UBEZSGXY.mjs.map +0 -7
- package/dist/lib/neutral/chunk-UI6MWK5W.mjs.map +0 -7
- package/dist/lib/neutral/chunk-V36VO5SS.mjs.map +0 -7
- package/dist/lib/neutral/chunk-WAK4DMFV.mjs.map +0 -7
- package/dist/lib/neutral/chunk-YAHXAYOW.mjs +0 -56
- package/dist/lib/neutral/chunk-YAHXAYOW.mjs.map +0 -7
- package/dist/lib/neutral/chunk-YS6Q3XAD.mjs +0 -50
- package/dist/lib/neutral/chunk-YS6Q3XAD.mjs.map +0 -7
- package/dist/types/src/Extension.d.ts +0 -80
- package/dist/types/src/Extension.d.ts.map +0 -1
- package/dist/types/src/Extension.test.d.ts +0 -2
- package/dist/types/src/Extension.test.d.ts.map +0 -1
- package/dist/types/src/SchemaRegistry.d.ts +0 -84
- package/dist/types/src/SchemaRegistry.d.ts.map +0 -1
- package/dist/types/src/internal/Obj/ids.d.ts +0 -6
- package/dist/types/src/internal/Obj/ids.d.ts.map +0 -1
- package/dist/types/src/internal/Query.d.ts.map +0 -1
- package/dist/types/src/internal/Type/echo-schema.d.ts +0 -181
- package/dist/types/src/internal/Type/echo-schema.d.ts.map +0 -1
- package/dist/types/src/internal/Type/persistent-schema.d.ts +0 -20
- package/dist/types/src/internal/Type/persistent-schema.d.ts.map +0 -1
- package/src/Extension.test.ts +0 -235
- package/src/Extension.ts +0 -122
- package/src/SchemaRegistry.ts +0 -106
- package/src/internal/Obj/ids.ts +0 -12
- package/src/internal/Type/echo-schema.ts +0 -423
- package/src/internal/Type/persistent-schema.ts +0 -33
- /package/dist/lib/neutral/{Extension.mjs.map → Registry.mjs.map} +0 -0
- /package/dist/lib/neutral/{SchemaRegistry.mjs.map → Scope.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-7RO7CPBZ.mjs.map → chunk-IGK6FN65.mjs.map} +0 -0
package/src/Relation.test.ts
CHANGED
|
@@ -44,13 +44,13 @@ describe('Relation', () => {
|
|
|
44
44
|
});
|
|
45
45
|
const snapshot = Relation.getSnapshot(rel);
|
|
46
46
|
|
|
47
|
-
//
|
|
48
|
-
expect(Relation.
|
|
49
|
-
expect(Relation.
|
|
47
|
+
// getSourceURI - works with both.
|
|
48
|
+
expect(Relation.getSourceURI(rel)).toBeDefined();
|
|
49
|
+
expect(Relation.getSourceURI(snapshot)).toBeDefined();
|
|
50
50
|
|
|
51
|
-
//
|
|
52
|
-
expect(Relation.
|
|
53
|
-
expect(Relation.
|
|
51
|
+
// getTargetURI - works with both.
|
|
52
|
+
expect(Relation.getTargetURI(rel)).toBeDefined();
|
|
53
|
+
expect(Relation.getTargetURI(snapshot)).toBeDefined();
|
|
54
54
|
|
|
55
55
|
// getSource - works with both.
|
|
56
56
|
expect(Relation.getSource(rel)).toBeDefined();
|
|
@@ -61,12 +61,12 @@ describe('Relation', () => {
|
|
|
61
61
|
expect(Relation.getTarget(snapshot)).toBeDefined();
|
|
62
62
|
|
|
63
63
|
// getDXN - works with both.
|
|
64
|
-
expect(Relation.
|
|
65
|
-
expect(Relation.
|
|
64
|
+
expect(Relation.getURI(rel)).toBeDefined();
|
|
65
|
+
expect(Relation.getURI(snapshot)).toBeDefined();
|
|
66
66
|
|
|
67
67
|
// getTypename - works with both.
|
|
68
|
-
expect(Relation.getTypename(rel)).toBe('com.example.type.
|
|
69
|
-
expect(Relation.getTypename(snapshot)).toBe('com.example.type.
|
|
68
|
+
expect(Relation.getTypename(rel)).toBe('com.example.type.hasManager');
|
|
69
|
+
expect(Relation.getTypename(snapshot)).toBe('com.example.type.hasManager');
|
|
70
70
|
|
|
71
71
|
// getMeta - works with both.
|
|
72
72
|
expect(Relation.getMeta(rel)).toBeDefined();
|
package/src/Relation.ts
CHANGED
|
@@ -8,17 +8,20 @@ import * as Schema from 'effect/Schema';
|
|
|
8
8
|
|
|
9
9
|
import { raise } from '@dxos/debug';
|
|
10
10
|
import type { ForeignKey } from '@dxos/echo-protocol';
|
|
11
|
-
import {
|
|
11
|
+
import { SchemaEx } from '@dxos/effect';
|
|
12
12
|
import { assertArgument, invariant } from '@dxos/invariant';
|
|
13
|
-
import {
|
|
13
|
+
import { EID, type EntityId, type URI, DXN } from '@dxos/keys';
|
|
14
14
|
import { assumeType } from '@dxos/util';
|
|
15
15
|
|
|
16
16
|
import type * as Database from './Database';
|
|
17
17
|
import * as Entity from './Entity';
|
|
18
18
|
import * as internal from './internal';
|
|
19
19
|
import * as entityInternal from './internal/Entity';
|
|
20
|
+
import * as objInternal from './internal/Obj';
|
|
20
21
|
import * as Obj from './Obj';
|
|
21
|
-
import type * as
|
|
22
|
+
import type * as Ref from './Ref';
|
|
23
|
+
import type * as Tag from './Tag';
|
|
24
|
+
import * as Type from './Type';
|
|
22
25
|
|
|
23
26
|
export type Endpoints<Source, Target> = {
|
|
24
27
|
[Source]: Source;
|
|
@@ -59,24 +62,20 @@ export interface Unknown extends BaseRelation<Obj.Unknown, Obj.Unknown> {}
|
|
|
59
62
|
* ```
|
|
60
63
|
*/
|
|
61
64
|
// TODO(dmaretskyi): Change ObjModule.Any to ObjModule.Unknown to have stricter types.
|
|
62
|
-
export const Unknown:
|
|
65
|
+
export const Unknown: internal.UnknownTypeSchema<Unknown, typeof Entity.Kind.Relation> = Schema.Struct({
|
|
63
66
|
id: Schema.String,
|
|
64
67
|
}).pipe(
|
|
65
68
|
Schema.extend(Schema.Record({ key: Schema.String, value: Schema.Unknown })),
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
Schema.annotations({
|
|
70
|
+
[internal.TypeAnnotationId]: {
|
|
71
|
+
kind: Entity.Kind.Relation,
|
|
72
|
+
typename: 'org.dxos.schema.anyRelation',
|
|
73
|
+
version: '0.0.0',
|
|
74
|
+
sourceSchema: DXN.make(internal.ANY_OBJECT_TYPENAME, internal.ANY_OBJECT_VERSION),
|
|
75
|
+
targetSchema: DXN.make(internal.ANY_OBJECT_TYPENAME, internal.ANY_OBJECT_VERSION),
|
|
76
|
+
},
|
|
74
77
|
}),
|
|
75
|
-
|
|
76
|
-
Object.assign(schema, {
|
|
77
|
-
[internal.SchemaKindId]: (schema as any)[internal.SchemaKindId],
|
|
78
|
-
}) as unknown as Type.Relation<Unknown, Obj.Any, Obj.Any>,
|
|
79
|
-
);
|
|
78
|
+
) as unknown as internal.UnknownTypeSchema<Unknown, typeof Entity.Kind.Relation>;
|
|
80
79
|
|
|
81
80
|
/**
|
|
82
81
|
* Relation type with specific source and target types.
|
|
@@ -89,7 +88,7 @@ export type OfShape<Source extends Obj.Unknown, Target extends Obj.Unknown, Prop
|
|
|
89
88
|
*/
|
|
90
89
|
interface BaseRelationSnapshot<Source, Target> extends internal.AnyEntity, Endpoints<Source, Target> {
|
|
91
90
|
readonly [Entity.SnapshotKindId]: internal.EntityKind.Relation;
|
|
92
|
-
readonly id:
|
|
91
|
+
readonly id: EntityId;
|
|
93
92
|
}
|
|
94
93
|
|
|
95
94
|
/**
|
|
@@ -129,18 +128,20 @@ export type TargetOf<A> = A extends Endpoints<infer _S, infer T> ? T : never;
|
|
|
129
128
|
/**
|
|
130
129
|
* Internal props type for relation instance creation.
|
|
131
130
|
*/
|
|
132
|
-
type MakePropsInternal<T extends
|
|
133
|
-
id?:
|
|
134
|
-
[Meta]?: internal.
|
|
131
|
+
type MakePropsInternal<T extends Endpoints<any, any>> = {
|
|
132
|
+
id?: EntityId;
|
|
133
|
+
[Meta]?: Partial<internal.EntityMeta>;
|
|
135
134
|
[Source]: T[Source];
|
|
136
135
|
[Target]: T[Target];
|
|
137
136
|
} & Entity.Properties<T>;
|
|
138
137
|
|
|
139
138
|
/**
|
|
140
|
-
* Props type for relation creation with a given schema.
|
|
141
|
-
*
|
|
139
|
+
* Props type for relation creation with a given schema. Accepts a `Type.AnyRelation`
|
|
140
|
+
* entity (created with `Type.makeRelation`) and derives the props shape via
|
|
141
|
+
* `Type.InstanceType`. Object-kind entities are rejected at the type level —
|
|
142
|
+
* use `Obj.MakeProps` for those.
|
|
142
143
|
*/
|
|
143
|
-
export type MakeProps<S extends Type.AnyRelation> = MakePropsInternal<
|
|
144
|
+
export type MakeProps<S extends Type.AnyRelation> = MakePropsInternal<Type.InstanceType<S>>;
|
|
144
145
|
|
|
145
146
|
/**
|
|
146
147
|
* Creates new relation.
|
|
@@ -151,10 +152,11 @@ export type MakeProps<S extends Type.AnyRelation> = MakePropsInternal<Schema.Sch
|
|
|
151
152
|
*/
|
|
152
153
|
// NOTE: Writing the definition this way (with generic over schema) makes typescript perfer to infer the type from the first param (this schema) rather than the second param (the props).
|
|
153
154
|
// TODO(dmaretskyi): Move meta into props.
|
|
154
|
-
export const make = <
|
|
155
|
-
|
|
156
|
-
props: NoInfer<MakeProps<
|
|
157
|
-
):
|
|
155
|
+
export const make = <T extends Type.AnyRelation>(
|
|
156
|
+
type: T,
|
|
157
|
+
props: NoInfer<MakeProps<T>>,
|
|
158
|
+
): Type.InstanceType<T> & Entity.OfKind<typeof Entity.Kind.Relation> => {
|
|
159
|
+
const schema = Type.getSchema(type);
|
|
158
160
|
assertArgument(
|
|
159
161
|
internal.getTypeAnnotation(schema)?.kind === internal.EntityKind.Relation,
|
|
160
162
|
'schema',
|
|
@@ -162,22 +164,48 @@ export const make = <S extends Type.AnyRelation>(
|
|
|
162
164
|
);
|
|
163
165
|
assertArgument(props[internal.ParentId] === undefined, 'props', 'Parent is not allowed for relations');
|
|
164
166
|
|
|
165
|
-
let meta: internal.
|
|
167
|
+
let meta: internal.EntityMeta | undefined = undefined;
|
|
166
168
|
|
|
167
169
|
if (props[internal.MetaId] != null) {
|
|
168
170
|
meta = props[internal.MetaId] as any;
|
|
169
171
|
delete props[internal.MetaId];
|
|
170
172
|
}
|
|
171
173
|
|
|
172
|
-
const sourceDXN = internal.
|
|
173
|
-
const targetDXN = internal.
|
|
174
|
+
const sourceDXN = internal.getObjectEchoUri(props[Source]) ?? raise(new Error('Unresolved relation source'));
|
|
175
|
+
const targetDXN = internal.getObjectEchoUri(props[Target]) ?? raise(new Error('Unresolved relation target'));
|
|
174
176
|
|
|
175
177
|
(props as any)[internal.RelationSourceDXNId] = sourceDXN;
|
|
176
178
|
(props as any)[internal.RelationTargetDXNId] = targetDXN;
|
|
177
179
|
|
|
178
|
-
|
|
180
|
+
// Pass the type entity through as `typeSource` so the resulting instance
|
|
181
|
+
// carries a back-reference resolvable via `Relation.getType` / `Entity.getType`.
|
|
182
|
+
return internal.makeObject(schema as any, props as any, meta, type as any) as any;
|
|
179
183
|
};
|
|
180
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Test if a value is an instance of a given relation type.
|
|
187
|
+
*
|
|
188
|
+
* Mirrors `Obj.instanceOf` but only accepts `Type.AnyRelation` — use
|
|
189
|
+
* `Obj.instanceOf` for objects and `Type.isType` for `Type.Type` entities.
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```ts
|
|
193
|
+
* const isEmployedBy = Relation.instanceOf(EmployedBy);
|
|
194
|
+
* if (isEmployedBy(relation)) {
|
|
195
|
+
* // relation is EmployedBy
|
|
196
|
+
* }
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
export const instanceOf: {
|
|
200
|
+
<S extends Type.AnyRelation>(schema: S): (value: unknown) => value is Type.InstanceType<S>;
|
|
201
|
+
<S extends Type.AnyRelation>(schema: S, value: unknown): value is Type.InstanceType<S>;
|
|
202
|
+
} = ((...args: [schema: Type.AnyRelation, value?: unknown]) => {
|
|
203
|
+
if (args.length === 1) {
|
|
204
|
+
return (entity: unknown) => internal.isInstanceOf(args[0], entity);
|
|
205
|
+
}
|
|
206
|
+
return internal.isInstanceOf(args[0], args[1]);
|
|
207
|
+
}) as any;
|
|
208
|
+
|
|
181
209
|
/**
|
|
182
210
|
* Type guard for relations.
|
|
183
211
|
* Returns true for both reactive relations and relation snapshots.
|
|
@@ -203,29 +231,29 @@ export const isSnapshot = (value: unknown): value is Snapshot => {
|
|
|
203
231
|
};
|
|
204
232
|
|
|
205
233
|
/**
|
|
206
|
-
* @returns Relation source
|
|
234
|
+
* @returns Relation source URI.
|
|
207
235
|
* Accepts both reactive relations and snapshots.
|
|
208
236
|
* @throws If the object is not a relation.
|
|
209
237
|
*/
|
|
210
|
-
export const
|
|
238
|
+
export const getSourceURI = (value: Unknown | Snapshot): EID.EID => {
|
|
211
239
|
assertArgument(isRelation(value), 'Expected a relation');
|
|
212
240
|
assumeType<internal.InternalObjectProps>(value);
|
|
213
|
-
const
|
|
214
|
-
invariant(
|
|
215
|
-
return
|
|
241
|
+
const uri = (value as internal.InternalObjectProps)[internal.RelationSourceDXNId];
|
|
242
|
+
invariant(EID.isEID(uri));
|
|
243
|
+
return uri;
|
|
216
244
|
};
|
|
217
245
|
|
|
218
246
|
/**
|
|
219
|
-
* @returns Relation target
|
|
247
|
+
* @returns Relation target URI.
|
|
220
248
|
* Accepts both reactive relations and snapshots.
|
|
221
249
|
* @throws If the object is not a relation.
|
|
222
250
|
*/
|
|
223
|
-
export const
|
|
251
|
+
export const getTargetURI = (value: Unknown | Snapshot): EID.EID => {
|
|
224
252
|
assertArgument(isRelation(value), 'Expected a relation');
|
|
225
253
|
assumeType<internal.InternalObjectProps>(value);
|
|
226
|
-
const
|
|
227
|
-
invariant(
|
|
228
|
-
return
|
|
254
|
+
const uri = (value as internal.InternalObjectProps)[internal.RelationTargetDXNId];
|
|
255
|
+
invariant(EID.isEID(uri));
|
|
256
|
+
return uri;
|
|
229
257
|
};
|
|
230
258
|
|
|
231
259
|
/**
|
|
@@ -264,7 +292,7 @@ export const getTarget = <T extends Unknown | Snapshot>(relation: T): TargetOf<T
|
|
|
264
292
|
|
|
265
293
|
/**
|
|
266
294
|
* Makes all properties mutable recursively.
|
|
267
|
-
* Used to provide a mutable view of a relation within `Relation.
|
|
295
|
+
* Used to provide a mutable view of a relation within `Relation.update`.
|
|
268
296
|
*/
|
|
269
297
|
export type Mutable<T> = internal.Mutable<T>;
|
|
270
298
|
|
|
@@ -272,10 +300,10 @@ export type Mutable<T> = internal.Mutable<T>;
|
|
|
272
300
|
* Perform mutations on an echo relation within a controlled context.
|
|
273
301
|
*
|
|
274
302
|
* All mutations within the callback are batched and trigger a single notification
|
|
275
|
-
* when the callback completes. Direct mutations outside of `Relation.
|
|
303
|
+
* when the callback completes. Direct mutations outside of `Relation.update` will throw
|
|
276
304
|
* an error for echo relations.
|
|
277
305
|
*
|
|
278
|
-
* @param relation - The echo relation to mutate. Use `Obj.
|
|
306
|
+
* @param relation - The echo relation to mutate. Use `Obj.update` for objects.
|
|
279
307
|
* @param callback - The callback that performs mutations on the relation.
|
|
280
308
|
*
|
|
281
309
|
* @example
|
|
@@ -286,15 +314,15 @@ export type Mutable<T> = internal.Mutable<T>;
|
|
|
286
314
|
* role: 'Engineer',
|
|
287
315
|
* });
|
|
288
316
|
*
|
|
289
|
-
* // Mutate within Relation.
|
|
290
|
-
* Relation.
|
|
317
|
+
* // Mutate within Relation.update
|
|
318
|
+
* Relation.update(worksFor, (obj) => {
|
|
291
319
|
* obj.role = 'Senior Engineer';
|
|
292
320
|
* });
|
|
293
321
|
* ```
|
|
294
322
|
*
|
|
295
|
-
* Note: Only accepts relations. Use `Obj.
|
|
323
|
+
* Note: Only accepts relations. Use `Obj.update` for objects.
|
|
296
324
|
*/
|
|
297
|
-
export const
|
|
325
|
+
export const update = <T extends Unknown>(relation: T, callback: internal.ChangeCallback<T>): void => {
|
|
298
326
|
internal.change(relation, callback);
|
|
299
327
|
};
|
|
300
328
|
|
|
@@ -332,12 +360,12 @@ export const subscribe = (rel: Unknown, callback: () => void): (() => void) => {
|
|
|
332
360
|
* Accepts both reactive relations and snapshots.
|
|
333
361
|
*/
|
|
334
362
|
export const getValue = (rel: Unknown | Snapshot, path: readonly (string | number)[]): any => {
|
|
335
|
-
return
|
|
363
|
+
return SchemaEx.getValue(rel, SchemaEx.createJsonPath(path));
|
|
336
364
|
};
|
|
337
365
|
|
|
338
366
|
/**
|
|
339
367
|
* Set a deeply nested property on a relation.
|
|
340
|
-
* Must be called within a `Relation.
|
|
368
|
+
* Must be called within a `Relation.update` callback.
|
|
341
369
|
*
|
|
342
370
|
* NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
|
|
343
371
|
* parameters, so there is no compile-time error. Enforcement is runtime-only.
|
|
@@ -350,21 +378,30 @@ export const setValue: (rel: Mutable<Unknown>, path: readonly (string | number)[
|
|
|
350
378
|
//
|
|
351
379
|
|
|
352
380
|
/**
|
|
353
|
-
* Get the
|
|
354
|
-
*
|
|
381
|
+
* Get the canonical URI of the relation. Returns `URI.URI` — today always an EID,
|
|
382
|
+
* but future entity kinds may surface other URI schemes; narrow with `EID.parse(uri)`
|
|
383
|
+
* or `DXN.tryMake(uri)` at the point of use. Accepts both reactive relations and snapshots.
|
|
384
|
+
*
|
|
385
|
+
* @param options.prefer - Controls the URI form (see {@link internal.GetURIOptions}).
|
|
355
386
|
*/
|
|
356
|
-
export const
|
|
387
|
+
export const getURI = (entity: Unknown | Snapshot, options?: internal.GetURIOptions): URI.URI =>
|
|
388
|
+
internal.getUri(entity, options);
|
|
357
389
|
|
|
358
390
|
/**
|
|
359
391
|
* @returns The DXN of the relation's type.
|
|
360
392
|
*/
|
|
361
|
-
export const
|
|
393
|
+
export const getTypeURI: (obj: internal.AnyProperties) => URI.URI | undefined = internal.getTypeURI;
|
|
362
394
|
|
|
363
395
|
/**
|
|
364
|
-
* Get the
|
|
365
|
-
*
|
|
396
|
+
* Get the type entity (`Type.AnyRelation`) the relation was created from.
|
|
397
|
+
*
|
|
398
|
+
* Returns `undefined` when the relation's type isn't registered in this
|
|
399
|
+
* runtime (e.g. a freshly deserialized snapshot whose type entity hasn't been
|
|
400
|
+
* wired up yet, or a relation loaded from storage before its schema is known).
|
|
401
|
+
* To get the Effect Schema from the returned entity, use `Type.getSchema(...)`.
|
|
366
402
|
*/
|
|
367
|
-
export const
|
|
403
|
+
export const getType = (relation: Unknown | Snapshot): Type.AnyRelation | undefined =>
|
|
404
|
+
internal.getType(relation) as Type.AnyRelation | undefined;
|
|
368
405
|
|
|
369
406
|
/**
|
|
370
407
|
* @returns The typename of the relation's type.
|
|
@@ -394,18 +431,18 @@ export const getDatabase = (entity: Unknown | Snapshot): Database.Database | und
|
|
|
394
431
|
export const Meta = internal.MetaId;
|
|
395
432
|
|
|
396
433
|
/**
|
|
397
|
-
* Deeply read-only version of
|
|
434
|
+
* Deeply read-only version of EntityMeta.
|
|
398
435
|
*/
|
|
399
436
|
export type ReadonlyMeta = internal.ReadonlyMeta;
|
|
400
437
|
|
|
401
438
|
/**
|
|
402
|
-
* Mutable meta type returned by `Relation.getMeta` inside a `Relation.
|
|
439
|
+
* Mutable meta type returned by `Relation.getMeta` inside a `Relation.update` callback.
|
|
403
440
|
*/
|
|
404
441
|
export type Meta = internal.Meta;
|
|
405
442
|
|
|
406
443
|
/**
|
|
407
444
|
* Get the metadata for a relation.
|
|
408
|
-
* Returns mutable meta when passed a mutable relation (inside `Relation.
|
|
445
|
+
* Returns mutable meta when passed a mutable relation (inside `Relation.update` callback).
|
|
409
446
|
* Returns read-only meta when passed a regular relation or snapshot.
|
|
410
447
|
*/
|
|
411
448
|
// TODO(wittjosiah): When passed a Snapshot, should return a snapshot of meta, not the live meta proxy.
|
|
@@ -423,7 +460,7 @@ export const getKeys = (entity: Unknown | Snapshot, source: string): ForeignKey[
|
|
|
423
460
|
|
|
424
461
|
/**
|
|
425
462
|
* Delete all keys from the relation for the specified source.
|
|
426
|
-
* Must be called within a `Relation.
|
|
463
|
+
* Must be called within a `Relation.update` callback.
|
|
427
464
|
*
|
|
428
465
|
* NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
|
|
429
466
|
* parameters, so there is no compile-time error. Enforcement is runtime-only.
|
|
@@ -432,21 +469,21 @@ export const deleteKeys = (entity: Mutable<Unknown>, source: string): void => in
|
|
|
432
469
|
|
|
433
470
|
/**
|
|
434
471
|
* Add a tag to the relation.
|
|
435
|
-
* Must be called within a `Relation.
|
|
472
|
+
* Must be called within a `Relation.update` callback.
|
|
436
473
|
*
|
|
437
474
|
* NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
|
|
438
475
|
* parameters, so there is no compile-time error. Enforcement is runtime-only.
|
|
439
476
|
*/
|
|
440
|
-
export const addTag = (entity: Mutable<Unknown>, tag:
|
|
477
|
+
export const addTag = (entity: Mutable<Unknown>, tag: Ref.Ref<Tag.Tag>): void => internal.addTag(entity, tag);
|
|
441
478
|
|
|
442
479
|
/**
|
|
443
480
|
* Remove a tag from the relation.
|
|
444
|
-
* Must be called within a `Relation.
|
|
481
|
+
* Must be called within a `Relation.update` callback.
|
|
445
482
|
*
|
|
446
483
|
* NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
|
|
447
484
|
* parameters, so there is no compile-time error. Enforcement is runtime-only.
|
|
448
485
|
*/
|
|
449
|
-
export const removeTag = (entity: Mutable<Unknown>, tag:
|
|
486
|
+
export const removeTag = (entity: Mutable<Unknown>, tag: Ref.Ref<Tag.Tag>): void => internal.removeTag(entity, tag);
|
|
450
487
|
|
|
451
488
|
/**
|
|
452
489
|
* Check if the relation is deleted.
|
|
@@ -461,12 +498,16 @@ export const isDeleted = (entity: Unknown | Snapshot): boolean => internal.isDel
|
|
|
461
498
|
/**
|
|
462
499
|
* Get the label of the relation.
|
|
463
500
|
* Accepts both reactive relations and snapshots.
|
|
501
|
+
*
|
|
502
|
+
* @param options.fallback `'typename'` returns the relation's typename when no
|
|
503
|
+
* label is set (e.g. `org.dxos.type.table`).
|
|
464
504
|
*/
|
|
465
|
-
export const getLabel = (entity: Unknown | Snapshot): string | undefined =>
|
|
505
|
+
export const getLabel = (entity: Unknown | Snapshot, options?: internal.GetLabelOptions): string | undefined =>
|
|
506
|
+
internal.getLabel(entity, options);
|
|
466
507
|
|
|
467
508
|
/**
|
|
468
509
|
* Set the label of the relation.
|
|
469
|
-
* Must be called within a `Relation.
|
|
510
|
+
* Must be called within a `Relation.update` callback.
|
|
470
511
|
*
|
|
471
512
|
* NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
|
|
472
513
|
* parameters, so there is no compile-time error. Enforcement is runtime-only.
|
|
@@ -481,7 +522,7 @@ export const getDescription = (entity: Unknown | Snapshot): string | undefined =
|
|
|
481
522
|
|
|
482
523
|
/**
|
|
483
524
|
* Set the description of the relation.
|
|
484
|
-
* Must be called within a `Relation.
|
|
525
|
+
* Must be called within a `Relation.update` callback.
|
|
485
526
|
*
|
|
486
527
|
* NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
|
|
487
528
|
* parameters, so there is no compile-time error. Enforcement is runtime-only.
|
|
@@ -535,3 +576,9 @@ export type Version = internal.EntityVersion;
|
|
|
535
576
|
* Accepts both reactive relations and snapshots.
|
|
536
577
|
*/
|
|
537
578
|
export const version = (entity: Unknown | Snapshot): Version => internal.version(entity);
|
|
579
|
+
|
|
580
|
+
//
|
|
581
|
+
// Atoms
|
|
582
|
+
//
|
|
583
|
+
|
|
584
|
+
export const atom = objInternal.makeRelation;
|
package/src/Scope.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
// @import-as-namespace
|
|
6
|
+
|
|
7
|
+
import { type QueryAST } from '@dxos/echo-protocol';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Scope targeting a space's automerge documents.
|
|
11
|
+
*
|
|
12
|
+
* With no `spaceId`, targets the owning space — i.e. the space of whichever database
|
|
13
|
+
* executes the query — so callers can reference "this space" without looking up its id.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* db.query(Filter.type(Person).from(Scope.space())); // owning space
|
|
18
|
+
* db.query(Filter.type(Person).from(Scope.space({ id: otherSpaceId }))); // a specific space
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export const space = (options?: { id?: string; includeAllFeeds?: boolean }): QueryAST.SpaceScope => ({
|
|
22
|
+
_tag: 'space',
|
|
23
|
+
...(options?.id !== undefined ? { spaceId: options.id } : {}),
|
|
24
|
+
...(options?.includeAllFeeds ? { includeAllFeeds: true } : {}),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Scope targeting a code-shipped object/type registry.
|
|
29
|
+
*
|
|
30
|
+
* - `'local'` — the in-process registry attached to the hypergraph (default).
|
|
31
|
+
* - `'remote'` — a remote registry service (not yet implemented).
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* // Discover all types — persisted in the space and code-shipped in the registry.
|
|
36
|
+
* db.query(Filter.type(Type.Type).from(Scope.space(), Scope.registry()));
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export const registry = (location: 'local' | 'remote' = 'local'): QueryAST.RegistryScope => ({
|
|
40
|
+
_tag: 'registry',
|
|
41
|
+
location,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Scope targeting a specific feed (by its underlying queue EID).
|
|
46
|
+
*/
|
|
47
|
+
export const feed = (feedUri: string): QueryAST.FeedScope => ({
|
|
48
|
+
_tag: 'feed',
|
|
49
|
+
feedUri,
|
|
50
|
+
});
|
package/src/Tag.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Tag
|
|
2
|
+
|
|
3
|
+
`Tag` is the ECHO type for labelling other objects. The schema is tiny — `{ label, hue? }` — but the _attachment pattern_ varies by use case. This doc covers what's available and which pattern to use.
|
|
4
|
+
|
|
5
|
+
## What `Tag` is
|
|
6
|
+
|
|
7
|
+
Definition: [`Tag.ts`](./src/Tag.ts) — `Schema.Struct({ label: String, hue?: String })` with DXN `org.dxos.type.tag@0.1.0`. Carries the `SystemTypeAnnotation` so it's treated as a built-in type by the ECHO runtime.
|
|
8
|
+
|
|
9
|
+
Helpers on the same module:
|
|
10
|
+
|
|
11
|
+
- `Tag.make(props)` — constructor.
|
|
12
|
+
- `Tag.Map` — `Record<string, Tag>` alias used by call-site indexes.
|
|
13
|
+
- `Tag.createTagList(tags)` — `Map → Tag[]`, sorted by label.
|
|
14
|
+
- `Tag.findTagByLabel(tags, name)` — case-insensitive label lookup.
|
|
15
|
+
- `Tag.sortTags(a, b)` — `localeCompare` on label.
|
|
16
|
+
|
|
17
|
+
### Colour (`hue`)
|
|
18
|
+
|
|
19
|
+
`hue` is a Tailwind colour name (`red`, `orange`, `amber`, …). The canonical list lives in [`IconAnnotation`'s schema](./src/internal/Annotation/annotations.ts) (search `IconAnnotationSchema`). Surfaces that render chips read `hue` to colour the chip; rendering hashes the tag id as a fallback when `hue` is absent.
|
|
20
|
+
|
|
21
|
+
## Attachment patterns
|
|
22
|
+
|
|
23
|
+
Three ways an object can carry tags. Pick the one that matches your storage shape:
|
|
24
|
+
|
|
25
|
+
### 1. `Obj.getMeta(obj).tags` — DXN refs on the object's metadata
|
|
26
|
+
|
|
27
|
+
The canonical user-tagging path. Each tag lives as a standalone `Tag` object in the space; the _target_ object holds an array of DXN refs to those tags inside its metadata bag. The form layer's [`ObjectProperties`](../../ui/react-ui-form/src/components/ObjectProperties) writes these via the `pinnedTags` control.
|
|
28
|
+
|
|
29
|
+
Use when: the target object is mutable. Tags can be added/removed cheaply by editing the metadata.
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
const tag = Obj.make(Tag.Tag, { label: 'important', hue: 'amber' });
|
|
33
|
+
db.add(tag);
|
|
34
|
+
Obj.update(target, (t) => {
|
|
35
|
+
Obj.getMeta(t).tags = [tag.dxn];
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 2. Container-owned tag map — inverse index on the parent
|
|
40
|
+
|
|
41
|
+
For containers that hold immutable-in-feed objects (mailboxes hold messages, magazines hold posts), the children can't carry tag refs because they're immutable. Instead, the container holds an inverted `tagId → Ref<child>[]` map. Tag _definitions_ live in the same map alongside the assignments.
|
|
42
|
+
|
|
43
|
+
Use when: the children are append-only feed records, OR you need a fast "all objects tagged X" query without scanning each child.
|
|
44
|
+
|
|
45
|
+
Reference shape (from plugin-inbox's [`Mailbox.tags`](../../plugins/plugin-inbox/src/types/Mailbox.ts)):
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
Mailbox.tags: Record<TagId, {
|
|
49
|
+
label: string,
|
|
50
|
+
hue?: string,
|
|
51
|
+
source?: 'provider' | 'user',
|
|
52
|
+
messages: Ref<Message>[],
|
|
53
|
+
}>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Tag-id strategy depends on origin:
|
|
57
|
+
|
|
58
|
+
| source | tag id | rationale |
|
|
59
|
+
| ----------------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------- |
|
|
60
|
+
| provider-synced (e.g. Gmail labels) | external id (Gmail's `Label_123`) | preserves re-sync idempotence — same external id → same map entry, no duplicates |
|
|
61
|
+
| user-applied | random `EntityId` | stable across renames; case-insensitive label dedupe via `findTagByLabel` at create time |
|
|
62
|
+
|
|
63
|
+
Trade-offs considered and rejected:
|
|
64
|
+
|
|
65
|
+
- Slug from label (`kebab-case(label)`) — natural dedupe but renaming a tag breaks references that point at the old key.
|
|
66
|
+
- EntityId for everything — uniform but Gmail re-syncs would duplicate provider tags every run unless you also dedupe by label, which loses the external id.
|
|
67
|
+
|
|
68
|
+
### 3. `HasSubject` relation (deprecated)
|
|
69
|
+
|
|
70
|
+
The older pattern: a relation with `Source = Tag, Target = Object`. Lives at [`@dxos/types/HasSubject`](../../sdk/types/src/types/HasSubject.ts) and is marked `@deprecated`.
|
|
71
|
+
|
|
72
|
+
Use when: never, for new code. Existing data is being migrated to one of the two patterns above. The shape is functionally identical to (1), but doing it via a separate relation creates a query overhead (walk all relations for the object) that (1) avoids by inlining the refs.
|
|
73
|
+
|
|
74
|
+
## Hue conventions
|
|
75
|
+
|
|
76
|
+
Always store the Tailwind colour name (e.g. `'amber'`), not a hex. Surfaces translate via `data-hue` on the chip, which the design system maps to the right shade. See [`getHashStyles`](../../ui/react-ui-components) for the fallback hash when `hue` is unset.
|
|
77
|
+
|
|
78
|
+
## plugin-inbox: how the inbox uses Tag
|
|
79
|
+
|
|
80
|
+
Single source of truth: [`Mailbox.tags`](../../plugins/plugin-inbox/src/types/Mailbox.ts). Pattern 2 (container map). Replaces both the older `Mailbox.labels` (Gmail provider dictionary) and the `HasSubject`-relation user-tagging path with one record.
|
|
81
|
+
|
|
82
|
+
- Provider labels: `syncLabels` writes `mailbox.tags[gmailLabelId] = { label, source: 'provider', messages: [...] }`. Gmail's id is the map key so re-sync is idempotent.
|
|
83
|
+
- Per-message provider assignments: at sync time, after appending a message to the feed, the sync loop pushes `Ref.make(message)` onto each `mailbox.tags[labelId].messages` it was given.
|
|
84
|
+
- User tags / extractor tags: `Mailbox.applyTag(mailbox, { label, hue? }, message)` find-or-creates a `source: 'user'` entry and pushes a Ref. Idempotent.
|
|
85
|
+
- UI: `Mailbox.buildMessageTagsIndex(mailbox)` inverts the map to `messageId → Tag[]` for `MessageStack` tile chips; `Mailbox.getTagsForMessage(mailbox, message)` for the single-message case in `MessageHeader`.
|
|
86
|
+
- Extractor tagging: extractors that want to tag the source message return `{ tags: [{ label, hue? }] }` in their `ExtractResult`; the `ExtractMessage` dispatcher applies them after persistence. See the trip extractor for an example (`tags: [{ label: 'trip', hue: 'sky' }]`).
|
|
87
|
+
|
|
88
|
+
Adopting the same pattern in a new plugin: pick this shape when your plugin owns a mutable container with immutable feed-stored children, OR when you want a fast "tagged-with-X" inverted lookup. Copy `applyTag` / `removeTag` / `buildMessageTagsIndex` / `getTagsForMessage` (≈ 80 lines, no plugin-specific logic) and you have a working tag system on day one.
|
package/src/Tag.ts
CHANGED
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
import * as Schema from 'effect/Schema';
|
|
8
8
|
|
|
9
|
+
import type { ForeignKey } from '@dxos/echo-protocol';
|
|
10
|
+
|
|
11
|
+
import type * as Database from './Database';
|
|
12
|
+
import * as Filter from './Filter';
|
|
9
13
|
import * as internal from './internal';
|
|
10
14
|
import * as Obj from './Obj';
|
|
11
15
|
import * as Type from './Type';
|
|
@@ -14,15 +18,13 @@ export const Tag = Schema.Struct({
|
|
|
14
18
|
label: Schema.String,
|
|
15
19
|
hue: Schema.optional(Schema.String), // TODO(burdon): Color name?
|
|
16
20
|
}).pipe(
|
|
17
|
-
Type.object({
|
|
18
|
-
typename: 'org.dxos.type.tag',
|
|
19
|
-
version: '0.1.0',
|
|
20
|
-
}),
|
|
21
21
|
internal.LabelAnnotation.set(['label']),
|
|
22
|
-
internal.
|
|
22
|
+
internal.HiddenAnnotation.set(true),
|
|
23
|
+
// Shared DXN so `meta.tags` (the `Ref<Tag>` schema) and this type stay in sync.
|
|
24
|
+
Type.makeObject(internal.TagTypeDXN),
|
|
23
25
|
);
|
|
24
26
|
|
|
25
|
-
export type Tag =
|
|
27
|
+
export type Tag = Type.InstanceType<typeof Tag>;
|
|
26
28
|
|
|
27
29
|
export const make = (props: Obj.MakeProps<typeof Tag>) => Obj.make(Tag, props);
|
|
28
30
|
|
|
@@ -39,3 +41,44 @@ export const findTagByLabel = (tags: Map | undefined, name: string): Tag | undef
|
|
|
39
41
|
const entry = Object.entries(tags ?? {}).find(([_, tag]) => tag.label.toLowerCase() === name.toLowerCase());
|
|
40
42
|
return entry ? { ...entry[1], id: entry[0] } : undefined;
|
|
41
43
|
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Finds or creates a {@link Tag} object in the database.
|
|
47
|
+
*
|
|
48
|
+
* - With a foreign `key` (system/provider tags): matched by that key; the label is kept current on
|
|
49
|
+
* re-sync. Use a stable key (e.g. `{ source: 'google.com/gmail/label', id }`) for tags whose
|
|
50
|
+
* identity is external or well-known.
|
|
51
|
+
* - Without a key (user tags): matched by case-insensitive label among tags that carry **no**
|
|
52
|
+
* foreign key, so it never collides with a keyed system/provider tag of the same label.
|
|
53
|
+
*/
|
|
54
|
+
export const findOrCreate = async (
|
|
55
|
+
db: Pick<Database.Database, 'query' | 'add'>,
|
|
56
|
+
options: { label: string; hue?: string; key?: ForeignKey },
|
|
57
|
+
): Promise<Tag> => {
|
|
58
|
+
const { label, hue, key } = options;
|
|
59
|
+
const withHue = hue ? { hue } : {};
|
|
60
|
+
if (key) {
|
|
61
|
+
const [existing] = await db.query(Filter.foreignKeys(Tag, [key])).run();
|
|
62
|
+
if (existing) {
|
|
63
|
+
// Keep label (and hue, when provided) current on re-sync. `hue` is only touched when supplied,
|
|
64
|
+
// so a label-only re-sync (e.g. Gmail) doesn't wipe a user-set colour.
|
|
65
|
+
if (existing.label !== label || (hue !== undefined && existing.hue !== hue)) {
|
|
66
|
+
Obj.update(existing, (existing) => {
|
|
67
|
+
existing.label = label;
|
|
68
|
+
if (hue !== undefined) {
|
|
69
|
+
existing.hue = hue;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return existing;
|
|
74
|
+
}
|
|
75
|
+
return db.add(Obj.make(Tag, { [Obj.Meta]: { keys: [key] }, label, ...withHue }));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const lowered = label.toLowerCase();
|
|
79
|
+
const candidates = await db.query(Filter.type(Tag)).run();
|
|
80
|
+
const existing = candidates.find(
|
|
81
|
+
(tag) => tag.label.toLowerCase() === lowered && (Obj.getMeta(tag).keys ?? []).length === 0,
|
|
82
|
+
);
|
|
83
|
+
return existing ?? db.add(make({ label, ...withHue }));
|
|
84
|
+
};
|