@dxos/echo 0.8.4-main.40e3dcdf1b → 0.8.4-main.43cb759274
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +102 -5
- package/README.md +7 -7
- package/dist/lib/neutral/Annotation.mjs +29 -6
- package/dist/lib/neutral/Database.mjs +8 -9
- package/dist/lib/neutral/Entity.mjs +29 -18
- package/dist/lib/neutral/Err.mjs +3 -3
- package/dist/lib/neutral/Feed.mjs +27 -19
- package/dist/lib/neutral/Filter.mjs +25 -15
- package/dist/lib/neutral/Format.mjs +23 -3
- package/dist/lib/neutral/JsonSchema.mjs +7 -8
- package/dist/lib/neutral/Key.mjs +9 -5
- package/dist/lib/neutral/Migration.mjs +18 -0
- package/dist/lib/neutral/Obj.mjs +25 -19
- package/dist/lib/neutral/Order.mjs +1 -1
- package/dist/lib/neutral/Query.mjs +19 -16
- package/dist/lib/neutral/QueryResult.mjs +1 -1
- package/dist/lib/neutral/Ref.mjs +10 -9
- package/dist/lib/neutral/Registry.mjs +14 -0
- package/dist/lib/neutral/Registry.mjs.map +7 -0
- package/dist/lib/neutral/Relation.mjs +26 -24
- package/dist/lib/neutral/Scope.mjs +12 -0
- package/dist/lib/neutral/Scope.mjs.map +7 -0
- package/dist/lib/neutral/Tag.mjs +17 -13
- package/dist/lib/neutral/Type.mjs +52 -26
- package/dist/lib/neutral/chunk-3DKP2EIN.mjs +31 -0
- package/dist/lib/neutral/chunk-3DKP2EIN.mjs.map +7 -0
- package/dist/lib/neutral/chunk-4BB4MFCN.mjs +154 -0
- package/dist/lib/neutral/chunk-4BB4MFCN.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-CIRHIEMW.mjs → chunk-4SFPZJVA.mjs} +92 -112
- package/dist/lib/neutral/chunk-4SFPZJVA.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-YWXWXIE5.mjs → chunk-4Z6GET2X.mjs} +3 -3
- package/dist/lib/neutral/chunk-4Z6GET2X.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-ANHVGJI4.mjs → chunk-7LOUAPYZ.mjs} +9 -5
- package/dist/lib/neutral/chunk-7LOUAPYZ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-43Y5DOS6.mjs → chunk-7OAFN3OX.mjs} +75 -112
- package/dist/lib/neutral/chunk-7OAFN3OX.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-BOZZPUXE.mjs → chunk-7PRCIDHH.mjs} +41 -81
- package/dist/lib/neutral/chunk-7PRCIDHH.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-UBEZSGXY.mjs → chunk-BBFJWWAV.mjs} +6 -6
- package/dist/lib/neutral/chunk-BBFJWWAV.mjs.map +7 -0
- package/dist/lib/neutral/chunk-BDQGMDIX.mjs +132 -0
- package/dist/lib/neutral/chunk-BDQGMDIX.mjs.map +7 -0
- package/dist/lib/neutral/chunk-CGTI5MXO.mjs +36 -0
- package/dist/lib/neutral/chunk-CGTI5MXO.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-OMUPQMLR.mjs → chunk-DKLUHO4T.mjs} +1 -1
- package/dist/lib/neutral/chunk-DKLUHO4T.mjs.map +7 -0
- package/dist/lib/neutral/chunk-DMN2CKPX.mjs +93 -0
- package/dist/lib/neutral/chunk-DMN2CKPX.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-UTBRYVQC.mjs → chunk-G6CFWUYH.mjs} +2 -2
- package/dist/lib/neutral/chunk-H26LSXVJ.mjs +653 -0
- package/dist/lib/neutral/chunk-H26LSXVJ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-FXEG7EOK.mjs → chunk-J3MNM65T.mjs} +9 -6
- package/dist/lib/neutral/chunk-J3MNM65T.mjs.map +7 -0
- package/dist/lib/neutral/chunk-JE7AOSWF.mjs +247 -0
- package/dist/lib/neutral/chunk-JE7AOSWF.mjs.map +7 -0
- package/dist/lib/neutral/chunk-LAF3LSWI.mjs +379 -0
- package/dist/lib/neutral/chunk-LAF3LSWI.mjs.map +7 -0
- package/dist/lib/neutral/chunk-LMNRFOVB.mjs +108 -0
- package/dist/lib/neutral/chunk-LMNRFOVB.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-WYOKA6AE.mjs → chunk-O6BH7EPN.mjs} +31 -4
- package/dist/lib/neutral/chunk-O6BH7EPN.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-KTAWP7GI.mjs → chunk-OIYW7R2G.mjs} +99 -46
- package/dist/lib/neutral/chunk-OIYW7R2G.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-TQQZLKB7.mjs → chunk-OYUG4FHF.mjs} +648 -1228
- package/dist/lib/neutral/chunk-OYUG4FHF.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-NQRLRYJM.mjs → chunk-Q5FKCVBC.mjs} +173 -60
- package/dist/lib/neutral/chunk-Q5FKCVBC.mjs.map +7 -0
- package/dist/lib/neutral/chunk-Q62IHV2N.mjs +41 -0
- package/dist/lib/neutral/chunk-Q62IHV2N.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-UFDK26FO.mjs → chunk-QVJDDG44.mjs} +69 -34
- package/dist/lib/neutral/chunk-QVJDDG44.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-B5OXLWZL.mjs → chunk-TFEWTY5A.mjs} +155 -129
- package/dist/lib/neutral/chunk-TFEWTY5A.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-UI6MWK5W.mjs → chunk-TTCSATUD.mjs} +1 -1
- package/dist/lib/neutral/{chunk-FZO7LQO7.mjs → chunk-VKWOFXT2.mjs} +22 -2
- package/dist/lib/neutral/{chunk-FZO7LQO7.mjs.map → chunk-VKWOFXT2.mjs.map} +1 -1
- package/dist/lib/neutral/{chunk-NXMFBIT5.mjs → chunk-ZACMEAYV.mjs} +89 -23
- package/dist/lib/neutral/chunk-ZACMEAYV.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +58 -38
- package/dist/lib/neutral/internal/index.mjs +131 -64
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/testing/index.mjs +222 -177
- package/dist/lib/neutral/testing/index.mjs.map +3 -3
- package/dist/types/src/Annotation.d.ts +108 -4
- package/dist/types/src/Annotation.d.ts.map +1 -1
- package/dist/types/src/Annotation.test.d.ts +2 -0
- package/dist/types/src/Annotation.test.d.ts.map +1 -0
- package/dist/types/src/Collection.d.ts +2 -3
- package/dist/types/src/Collection.d.ts.map +1 -1
- package/dist/types/src/Database.d.ts +56 -24
- package/dist/types/src/Database.d.ts.map +1 -1
- package/dist/types/src/Dataset.d.ts +17 -6
- package/dist/types/src/Dataset.d.ts.map +1 -1
- package/dist/types/src/Entity.d.ts +102 -26
- package/dist/types/src/Entity.d.ts.map +1 -1
- package/dist/types/src/Err.d.ts +27 -27
- package/dist/types/src/Err.d.ts.map +1 -1
- package/dist/types/src/Feed.d.ts +89 -25
- package/dist/types/src/Feed.d.ts.map +1 -1
- package/dist/types/src/Filter.d.ts +74 -11
- package/dist/types/src/Filter.d.ts.map +1 -1
- package/dist/types/src/Filter.test.d.ts +2 -0
- package/dist/types/src/Filter.test.d.ts.map +1 -0
- package/dist/types/src/Hypergraph.d.ts +14 -9
- package/dist/types/src/Hypergraph.d.ts.map +1 -1
- package/dist/types/src/Json.d.ts +33 -0
- package/dist/types/src/Json.d.ts.map +1 -0
- package/dist/types/src/Json.test.d.ts +2 -0
- package/dist/types/src/Json.test.d.ts.map +1 -0
- package/dist/types/src/JsonSchema.d.ts +2 -2
- package/dist/types/src/JsonSchema.d.ts.map +1 -1
- package/dist/types/src/Key.d.ts +1 -1
- package/dist/types/src/Key.d.ts.map +1 -1
- package/dist/types/src/Migration.d.ts +72 -0
- package/dist/types/src/Migration.d.ts.map +1 -0
- package/dist/types/src/Obj.d.ts +108 -65
- package/dist/types/src/Obj.d.ts.map +1 -1
- package/dist/types/src/Order.d.ts.map +1 -1
- package/dist/types/src/Query.d.ts +35 -10
- package/dist/types/src/Query.d.ts.map +1 -1
- package/dist/types/src/QueryResult.d.ts +9 -0
- package/dist/types/src/QueryResult.d.ts.map +1 -1
- package/dist/types/src/Ref.d.ts +15 -7
- package/dist/types/src/Ref.d.ts.map +1 -1
- package/dist/types/src/Registry.d.ts +131 -0
- package/dist/types/src/Registry.d.ts.map +1 -0
- package/dist/types/src/Relation.d.ts +72 -44
- package/dist/types/src/Relation.d.ts.map +1 -1
- package/dist/types/src/Scope.d.ts +34 -0
- package/dist/types/src/Scope.d.ts.map +1 -0
- package/dist/types/src/StateMap.d.ts +32 -0
- package/dist/types/src/StateMap.d.ts.map +1 -0
- package/dist/types/src/StateMap.test.d.ts +2 -0
- package/dist/types/src/StateMap.test.d.ts.map +1 -0
- package/dist/types/src/Tag.d.ts +21 -5
- package/dist/types/src/Tag.d.ts.map +1 -1
- package/dist/types/src/TagIndex.d.ts +36 -0
- package/dist/types/src/TagIndex.d.ts.map +1 -0
- package/dist/types/src/TagIndex.test.d.ts +2 -0
- package/dist/types/src/TagIndex.test.d.ts.map +1 -0
- package/dist/types/src/Tagging.d.ts +31 -0
- package/dist/types/src/Tagging.d.ts.map +1 -0
- package/dist/types/src/Type.d.ts +357 -96
- package/dist/types/src/Type.d.ts.map +1 -1
- package/dist/types/src/View.d.ts +2 -5
- package/dist/types/src/View.d.ts.map +1 -1
- package/dist/types/src/exemplars.test.d.ts +2 -0
- package/dist/types/src/exemplars.test.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +8 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/annotations.d.ts +79 -37
- package/dist/types/src/internal/Annotation/annotations.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/dictionary.d.ts +24 -0
- package/dist/types/src/internal/Annotation/dictionary.d.ts.map +1 -0
- package/dist/types/src/internal/Annotation/entity-dictionary.d.ts +14 -0
- package/dist/types/src/internal/Annotation/entity-dictionary.d.ts.map +1 -0
- package/dist/types/src/internal/Annotation/index.d.ts +4 -2
- package/dist/types/src/internal/Annotation/index.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/sorting.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/util.d.ts +14 -5
- package/dist/types/src/internal/Annotation/util.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/api.d.ts +3 -3
- package/dist/types/src/internal/Entity/api.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/entity.d.ts +72 -8
- package/dist/types/src/internal/Entity/entity.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/guard.d.ts +10 -0
- package/dist/types/src/internal/Entity/guard.d.ts.map +1 -0
- package/dist/types/src/internal/Entity/index.d.ts +2 -0
- package/dist/types/src/internal/Entity/index.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/model.d.ts +20 -17
- package/dist/types/src/internal/Entity/model.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/object.d.ts +3 -3
- package/dist/types/src/internal/Entity/object.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/relation.d.ts +30 -7
- package/dist/types/src/internal/Entity/relation.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/type-kind.d.ts +24 -0
- package/dist/types/src/internal/Entity/type-kind.d.ts.map +1 -0
- package/dist/types/src/internal/Entity/type-uri.d.ts +25 -0
- package/dist/types/src/internal/Entity/type-uri.d.ts.map +1 -0
- package/dist/types/src/internal/Entity/version.d.ts.map +1 -1
- package/dist/types/src/internal/Format/date.d.ts.map +1 -1
- package/dist/types/src/internal/Format/format.d.ts +3 -2
- package/dist/types/src/internal/Format/format.d.ts.map +1 -1
- package/dist/types/src/internal/Format/index.d.ts +2 -2
- package/dist/types/src/internal/Format/index.d.ts.map +1 -1
- package/dist/types/src/internal/Format/number.d.ts.map +1 -1
- package/dist/types/src/internal/Format/object.d.ts +3 -1
- package/dist/types/src/internal/Format/object.d.ts.map +1 -1
- package/dist/types/src/internal/Format/types.d.ts.map +1 -1
- package/dist/types/src/internal/JsonSchema/json-schema-normalize.d.ts.map +1 -1
- package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts +28 -28
- package/dist/types/src/internal/JsonSchema/json-schema-type.d.ts.map +1 -1
- package/dist/types/src/internal/JsonSchema/json-schema.d.ts +3 -2
- package/dist/types/src/internal/JsonSchema/json-schema.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/clone.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/common.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/create-object.d.ts +11 -12
- package/dist/types/src/internal/Obj/create-object.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/deleted.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/index.d.ts +0 -1
- package/dist/types/src/internal/Obj/index.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/json-serializer.d.ts +11 -10
- package/dist/types/src/internal/Obj/json-serializer.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/set-value.d.ts +1 -1
- package/dist/types/src/internal/Obj/set-value.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/snapshot.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/typed-object.d.ts +1 -1
- package/dist/types/src/internal/Query.d.ts +10 -0
- package/dist/types/src/internal/Query.d.ts.map +1 -0
- package/dist/types/src/internal/Ref/ref-array.d.ts +2 -2
- package/dist/types/src/internal/Ref/ref-array.d.ts.map +1 -1
- package/dist/types/src/internal/Ref/ref.d.ts +42 -19
- package/dist/types/src/internal/Ref/ref.d.ts.map +1 -1
- package/dist/types/src/internal/Type/compose.d.ts.map +1 -1
- package/dist/types/src/internal/Type/index.d.ts +1 -2
- package/dist/types/src/internal/Type/index.d.ts.map +1 -1
- package/dist/types/src/internal/Type/manipulation.d.ts +0 -1
- package/dist/types/src/internal/Type/manipulation.d.ts.map +1 -1
- package/dist/types/src/internal/Type/type-schema.d.ts +52 -0
- package/dist/types/src/internal/Type/type-schema.d.ts.map +1 -0
- package/dist/types/src/internal/common/api/meta.d.ts +14 -11
- package/dist/types/src/internal/common/api/meta.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/change-context.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/change-context.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/define-hidden-property.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/errors.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/errors.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/event-batch.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/json-serializer.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/make-object.d.ts +11 -5
- package/dist/types/src/internal/common/proxy/make-object.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/ownership.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/proxy-utils.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/reactive-array.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/reactive.d.ts +1 -1
- package/dist/types/src/internal/common/proxy/reactive.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/reactive.test.d.ts +2 -0
- package/dist/types/src/internal/common/proxy/reactive.test.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/schema-validator.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/typed-handler.d.ts +18 -2
- package/dist/types/src/internal/common/proxy/typed-handler.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/base.d.ts +4 -4
- package/dist/types/src/internal/common/types/base.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/entity.d.ts +63 -6
- package/dist/types/src/internal/common/types/entity.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/index.d.ts +1 -1
- package/dist/types/src/internal/common/types/index.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/meta.d.ts +23 -7
- package/dist/types/src/internal/common/types/meta.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/model-symbols.d.ts +8 -4
- package/dist/types/src/internal/common/types/model-symbols.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/typename.d.ts +7 -0
- package/dist/types/src/internal/common/types/typename.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/version.d.ts +1 -1
- package/dist/types/src/internal/common/types/well-known-types.d.ts +11 -0
- package/dist/types/src/internal/common/types/well-known-types.d.ts.map +1 -0
- package/dist/types/src/internal/index.d.ts +2 -0
- package/dist/types/src/internal/index.d.ts.map +1 -1
- package/dist/types/src/testing/test-data.d.ts +8 -8
- package/dist/types/src/testing/test-data.d.ts.map +1 -1
- package/dist/types/src/testing/test-schema.d.ts +83 -89
- package/dist/types/src/testing/test-schema.d.ts.map +1 -1
- package/dist/types/src/testing/util.d.ts +5 -3
- package/dist/types/src/testing/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +27 -19
- package/src/Annotation.test.ts +439 -0
- package/src/Annotation.ts +152 -4
- package/src/Collection.ts +6 -5
- package/src/Database.ts +117 -57
- package/src/Dataset.ts +10 -2
- package/src/Entity.test.ts +116 -6
- package/src/Entity.ts +130 -31
- package/src/Err.ts +4 -4
- package/src/Feed.ts +138 -43
- package/src/Filter.test.ts +90 -0
- package/src/Filter.ts +143 -27
- package/src/Hypergraph.ts +14 -9
- package/src/Json.test.ts +175 -0
- package/src/Json.ts +103 -0
- package/src/Key.ts +1 -1
- package/src/Migration.ts +114 -0
- package/src/Obj.test.ts +122 -19
- package/src/Obj.ts +279 -97
- package/src/Query.test.ts +317 -131
- package/src/Query.ts +181 -73
- package/src/QueryResult.ts +11 -0
- package/src/Ref.ts +22 -4
- package/src/Registry.ts +155 -0
- package/src/Relation.test.ts +10 -10
- package/src/Relation.ts +112 -71
- package/src/Scope.ts +50 -0
- package/src/StateMap.test.ts +56 -0
- package/src/StateMap.ts +99 -0
- package/src/Tag.md +88 -0
- package/src/Tag.ts +49 -6
- package/src/TagIndex.test.ts +57 -0
- package/src/TagIndex.ts +110 -0
- package/src/Tagging.ts +83 -0
- package/src/Type.test.ts +223 -18
- package/src/Type.ts +602 -132
- package/src/View.ts +11 -15
- package/src/exemplars.test.ts +21 -0
- package/src/index.ts +9 -3
- package/src/internal/Annotation/annotations.test.ts +82 -13
- package/src/internal/Annotation/annotations.ts +153 -115
- package/src/internal/Annotation/dictionary.ts +47 -0
- package/src/internal/Annotation/entity-dictionary.ts +40 -0
- package/src/internal/Annotation/index.ts +4 -2
- package/src/internal/Annotation/sorting.ts +0 -1
- package/src/internal/Annotation/util.ts +17 -8
- package/src/internal/Entity/api.ts +7 -8
- package/src/internal/Entity/entity.ts +196 -47
- package/src/internal/Entity/guard.ts +26 -0
- package/src/internal/Entity/index.ts +2 -0
- package/src/internal/Entity/model.ts +37 -28
- package/src/internal/Entity/object.ts +21 -6
- package/src/internal/Entity/relation.ts +68 -34
- package/src/internal/Entity/type-kind.ts +75 -0
- package/src/internal/Entity/type-uri.ts +87 -0
- package/src/internal/Entity/util.ts +10 -9
- package/src/internal/Entity/version.ts +0 -1
- package/src/internal/Format/date.test.ts +0 -1
- package/src/internal/Format/date.ts +0 -4
- package/src/internal/Format/format.test.ts +21 -1
- package/src/internal/Format/index.ts +2 -3
- package/src/internal/Format/object.ts +21 -4
- package/src/internal/Format/types.ts +1 -1
- package/src/internal/JsonSchema/annotations.ts +1 -1
- package/src/internal/JsonSchema/json-schema-type.ts +1 -1
- package/src/internal/JsonSchema/json-schema.test.ts +55 -142
- package/src/internal/JsonSchema/json-schema.ts +44 -31
- package/src/internal/Obj/clone.ts +9 -4
- package/src/internal/Obj/create-object.test.ts +13 -13
- package/src/internal/Obj/create-object.ts +68 -24
- package/src/internal/Obj/deleted.ts +1 -1
- package/src/internal/Obj/index.ts +0 -1
- package/src/internal/Obj/inspect.ts +4 -3
- package/src/internal/Obj/json-serializer.test.ts +102 -24
- package/src/internal/Obj/json-serializer.ts +105 -43
- package/src/internal/Obj/set-value.test.ts +31 -54
- package/src/internal/Obj/set-value.ts +1 -1
- package/src/internal/Obj/snapshot.ts +11 -4
- package/src/internal/Obj/typed-object.test.ts +9 -11
- package/src/internal/Obj/typed-object.ts +1 -1
- package/src/internal/Query.ts +159 -0
- package/src/internal/Ref/ref-array.ts +3 -4
- package/src/internal/Ref/ref.test.ts +17 -27
- package/src/internal/Ref/ref.ts +124 -59
- package/src/internal/Type/compose.test.ts +3 -2
- package/src/internal/Type/index.ts +1 -2
- package/src/internal/Type/manipulation.ts +0 -25
- package/src/internal/Type/type-schema.ts +60 -0
- package/src/internal/common/README.md +2 -2
- package/src/internal/common/api/meta.ts +19 -17
- package/src/internal/common/proxy/change-context.ts +1 -1
- package/src/internal/common/proxy/change.test.ts +118 -110
- package/src/internal/common/proxy/errors.ts +2 -2
- package/src/internal/common/proxy/handler.test.ts +1 -3
- package/src/internal/common/proxy/json-serializer.ts +26 -16
- package/src/internal/common/proxy/make-object.ts +43 -21
- package/src/internal/common/proxy/ownership.ts +2 -3
- package/src/internal/common/proxy/reactive-array.ts +1 -1
- package/src/internal/common/proxy/reactive.test.ts +54 -0
- package/src/internal/common/proxy/reactive.ts +11 -3
- package/src/internal/common/proxy/schema.test.ts +48 -86
- package/src/internal/common/proxy/typed-handler.test.ts +12 -12
- package/src/internal/common/proxy/typed-handler.ts +79 -19
- package/src/internal/common/proxy/typed-object.test.ts +16 -29
- package/src/internal/common/types/base.ts +4 -4
- package/src/internal/common/types/entity.ts +81 -2
- package/src/internal/common/types/index.ts +6 -1
- package/src/internal/common/types/meta.ts +49 -15
- package/src/internal/common/types/model-symbols.ts +16 -4
- package/src/internal/common/types/typename.ts +39 -3
- package/src/internal/common/types/well-known-types.ts +15 -0
- package/src/internal/index.ts +6 -0
- package/src/testing/api.test.ts +15 -10
- package/src/testing/test-data.ts +159 -100
- package/src/testing/test-schema.ts +22 -58
- package/src/testing/util.ts +14 -11
- package/dist/lib/neutral/SchemaRegistry.mjs +0 -2
- package/dist/lib/neutral/chunk-43Y5DOS6.mjs.map +0 -7
- package/dist/lib/neutral/chunk-724GQYEN.mjs +0 -56
- package/dist/lib/neutral/chunk-724GQYEN.mjs.map +0 -7
- package/dist/lib/neutral/chunk-ANHVGJI4.mjs.map +0 -7
- package/dist/lib/neutral/chunk-B5OXLWZL.mjs.map +0 -7
- package/dist/lib/neutral/chunk-BNCCGLJN.mjs +0 -7
- package/dist/lib/neutral/chunk-BNCCGLJN.mjs.map +0 -7
- package/dist/lib/neutral/chunk-BOZZPUXE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-CIRHIEMW.mjs.map +0 -7
- package/dist/lib/neutral/chunk-DYDJBZEG.mjs +0 -102
- package/dist/lib/neutral/chunk-DYDJBZEG.mjs.map +0 -7
- package/dist/lib/neutral/chunk-FXEG7EOK.mjs.map +0 -7
- package/dist/lib/neutral/chunk-KTAWP7GI.mjs.map +0 -7
- package/dist/lib/neutral/chunk-NEGC54NE.mjs +0 -130
- package/dist/lib/neutral/chunk-NEGC54NE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-NQRLRYJM.mjs.map +0 -7
- package/dist/lib/neutral/chunk-NXMFBIT5.mjs.map +0 -7
- package/dist/lib/neutral/chunk-OENWMTE6.mjs +0 -45
- package/dist/lib/neutral/chunk-OENWMTE6.mjs.map +0 -7
- package/dist/lib/neutral/chunk-OMUPQMLR.mjs.map +0 -7
- package/dist/lib/neutral/chunk-RMLF7JOZ.mjs +0 -97
- package/dist/lib/neutral/chunk-RMLF7JOZ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-SEMVAGBM.mjs +0 -355
- package/dist/lib/neutral/chunk-SEMVAGBM.mjs.map +0 -7
- package/dist/lib/neutral/chunk-TQQZLKB7.mjs.map +0 -7
- package/dist/lib/neutral/chunk-UBEZSGXY.mjs.map +0 -7
- package/dist/lib/neutral/chunk-UFDK26FO.mjs.map +0 -7
- package/dist/lib/neutral/chunk-VA2F47ZC.mjs +0 -152
- package/dist/lib/neutral/chunk-VA2F47ZC.mjs.map +0 -7
- package/dist/lib/neutral/chunk-WYOKA6AE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-YWXWXIE5.mjs.map +0 -7
- package/dist/types/src/SchemaRegistry.d.ts +0 -84
- package/dist/types/src/SchemaRegistry.d.ts.map +0 -1
- package/dist/types/src/internal/Obj/ids.d.ts +0 -6
- package/dist/types/src/internal/Obj/ids.d.ts.map +0 -1
- package/dist/types/src/internal/Type/echo-schema.d.ts +0 -181
- package/dist/types/src/internal/Type/echo-schema.d.ts.map +0 -1
- package/dist/types/src/internal/Type/persistent-schema.d.ts +0 -20
- package/dist/types/src/internal/Type/persistent-schema.d.ts.map +0 -1
- package/src/SchemaRegistry.ts +0 -106
- package/src/internal/Obj/ids.ts +0 -12
- package/src/internal/Type/echo-schema.ts +0 -424
- package/src/internal/Type/persistent-schema.ts +0 -33
- /package/dist/lib/neutral/{SchemaRegistry.mjs.map → Migration.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-UTBRYVQC.mjs.map → chunk-G6CFWUYH.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-UI6MWK5W.mjs.map → chunk-TTCSATUD.mjs.map} +0 -0
package/src/Relation.ts
CHANGED
|
@@ -10,15 +10,17 @@ import { raise } from '@dxos/debug';
|
|
|
10
10
|
import type { ForeignKey } from '@dxos/echo-protocol';
|
|
11
11
|
import { createJsonPath } 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
|
-
import * as entityInternal from './internal/Entity';
|
|
19
18
|
import * as internal from './internal';
|
|
19
|
+
import * as entityInternal from './internal/Entity';
|
|
20
20
|
import * as Obj from './Obj';
|
|
21
|
-
import type * as
|
|
21
|
+
import type * as Ref from './Ref';
|
|
22
|
+
import type * as Tag from './Tag';
|
|
23
|
+
import * as Type from './Type';
|
|
22
24
|
|
|
23
25
|
export type Endpoints<Source, Target> = {
|
|
24
26
|
[Source]: Source;
|
|
@@ -59,24 +61,20 @@ export interface Unknown extends BaseRelation<Obj.Unknown, Obj.Unknown> {}
|
|
|
59
61
|
* ```
|
|
60
62
|
*/
|
|
61
63
|
// TODO(dmaretskyi): Change ObjModule.Any to ObjModule.Unknown to have stricter types.
|
|
62
|
-
export const Unknown:
|
|
64
|
+
export const Unknown: internal.UnknownTypeSchema<Unknown, typeof Entity.Kind.Relation> = Schema.Struct({
|
|
63
65
|
id: Schema.String,
|
|
64
66
|
}).pipe(
|
|
65
67
|
Schema.extend(Schema.Record({ key: Schema.String, value: Schema.Unknown })),
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
Schema.annotations({
|
|
69
|
+
[internal.TypeAnnotationId]: {
|
|
70
|
+
kind: Entity.Kind.Relation,
|
|
71
|
+
typename: 'org.dxos.schema.anyRelation',
|
|
72
|
+
version: '0.0.0',
|
|
73
|
+
sourceSchema: DXN.make(internal.ANY_OBJECT_TYPENAME, internal.ANY_OBJECT_VERSION),
|
|
74
|
+
targetSchema: DXN.make(internal.ANY_OBJECT_TYPENAME, internal.ANY_OBJECT_VERSION),
|
|
75
|
+
},
|
|
74
76
|
}),
|
|
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
|
-
);
|
|
77
|
+
) as unknown as internal.UnknownTypeSchema<Unknown, typeof Entity.Kind.Relation>;
|
|
80
78
|
|
|
81
79
|
/**
|
|
82
80
|
* Relation type with specific source and target types.
|
|
@@ -89,7 +87,7 @@ export type OfShape<Source extends Obj.Unknown, Target extends Obj.Unknown, Prop
|
|
|
89
87
|
*/
|
|
90
88
|
interface BaseRelationSnapshot<Source, Target> extends internal.AnyEntity, Endpoints<Source, Target> {
|
|
91
89
|
readonly [Entity.SnapshotKindId]: internal.EntityKind.Relation;
|
|
92
|
-
readonly id:
|
|
90
|
+
readonly id: EntityId;
|
|
93
91
|
}
|
|
94
92
|
|
|
95
93
|
/**
|
|
@@ -129,18 +127,20 @@ export type TargetOf<A> = A extends Endpoints<infer _S, infer T> ? T : never;
|
|
|
129
127
|
/**
|
|
130
128
|
* Internal props type for relation instance creation.
|
|
131
129
|
*/
|
|
132
|
-
type MakePropsInternal<T extends
|
|
133
|
-
id?:
|
|
134
|
-
[Meta]?: internal.
|
|
130
|
+
type MakePropsInternal<T extends Endpoints<any, any>> = {
|
|
131
|
+
id?: EntityId;
|
|
132
|
+
[Meta]?: Partial<internal.EntityMeta>;
|
|
135
133
|
[Source]: T[Source];
|
|
136
134
|
[Target]: T[Target];
|
|
137
135
|
} & Entity.Properties<T>;
|
|
138
136
|
|
|
139
137
|
/**
|
|
140
|
-
* Props type for relation creation with a given schema.
|
|
141
|
-
*
|
|
138
|
+
* Props type for relation creation with a given schema. Accepts a `Type.AnyRelation`
|
|
139
|
+
* entity (created with `Type.makeRelation`) and derives the props shape via
|
|
140
|
+
* `Type.InstanceType`. Object-kind entities are rejected at the type level —
|
|
141
|
+
* use `Obj.MakeProps` for those.
|
|
142
142
|
*/
|
|
143
|
-
export type MakeProps<S extends Type.AnyRelation> = MakePropsInternal<
|
|
143
|
+
export type MakeProps<S extends Type.AnyRelation> = MakePropsInternal<Type.InstanceType<S>>;
|
|
144
144
|
|
|
145
145
|
/**
|
|
146
146
|
* Creates new relation.
|
|
@@ -151,10 +151,11 @@ export type MakeProps<S extends Type.AnyRelation> = MakePropsInternal<Schema.Sch
|
|
|
151
151
|
*/
|
|
152
152
|
// 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
153
|
// TODO(dmaretskyi): Move meta into props.
|
|
154
|
-
export const make = <
|
|
155
|
-
|
|
156
|
-
props: NoInfer<MakeProps<
|
|
157
|
-
):
|
|
154
|
+
export const make = <T extends Type.AnyRelation>(
|
|
155
|
+
type: T,
|
|
156
|
+
props: NoInfer<MakeProps<T>>,
|
|
157
|
+
): Type.InstanceType<T> & Entity.OfKind<typeof Entity.Kind.Relation> => {
|
|
158
|
+
const schema = Type.getSchema(type);
|
|
158
159
|
assertArgument(
|
|
159
160
|
internal.getTypeAnnotation(schema)?.kind === internal.EntityKind.Relation,
|
|
160
161
|
'schema',
|
|
@@ -162,22 +163,48 @@ export const make = <S extends Type.AnyRelation>(
|
|
|
162
163
|
);
|
|
163
164
|
assertArgument(props[internal.ParentId] === undefined, 'props', 'Parent is not allowed for relations');
|
|
164
165
|
|
|
165
|
-
let meta: internal.
|
|
166
|
+
let meta: internal.EntityMeta | undefined = undefined;
|
|
166
167
|
|
|
167
168
|
if (props[internal.MetaId] != null) {
|
|
168
169
|
meta = props[internal.MetaId] as any;
|
|
169
170
|
delete props[internal.MetaId];
|
|
170
171
|
}
|
|
171
172
|
|
|
172
|
-
const sourceDXN = internal.
|
|
173
|
-
const targetDXN = internal.
|
|
173
|
+
const sourceDXN = internal.getObjectEchoUri(props[Source]) ?? raise(new Error('Unresolved relation source'));
|
|
174
|
+
const targetDXN = internal.getObjectEchoUri(props[Target]) ?? raise(new Error('Unresolved relation target'));
|
|
174
175
|
|
|
175
176
|
(props as any)[internal.RelationSourceDXNId] = sourceDXN;
|
|
176
177
|
(props as any)[internal.RelationTargetDXNId] = targetDXN;
|
|
177
178
|
|
|
178
|
-
|
|
179
|
+
// Pass the type entity through as `typeSource` so the resulting instance
|
|
180
|
+
// carries a back-reference resolvable via `Relation.getType` / `Entity.getType`.
|
|
181
|
+
return internal.makeObject(schema as any, props as any, meta, type as any) as any;
|
|
179
182
|
};
|
|
180
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Test if a value is an instance of a given relation type.
|
|
186
|
+
*
|
|
187
|
+
* Mirrors `Obj.instanceOf` but only accepts `Type.AnyRelation` — use
|
|
188
|
+
* `Obj.instanceOf` for objects and `Type.isType` for `Type.Type` entities.
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* ```ts
|
|
192
|
+
* const isEmployedBy = Relation.instanceOf(EmployedBy);
|
|
193
|
+
* if (isEmployedBy(relation)) {
|
|
194
|
+
* // relation is EmployedBy
|
|
195
|
+
* }
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
export const instanceOf: {
|
|
199
|
+
<S extends Type.AnyRelation>(schema: S): (value: unknown) => value is Type.InstanceType<S>;
|
|
200
|
+
<S extends Type.AnyRelation>(schema: S, value: unknown): value is Type.InstanceType<S>;
|
|
201
|
+
} = ((...args: [schema: Type.AnyRelation, value?: unknown]) => {
|
|
202
|
+
if (args.length === 1) {
|
|
203
|
+
return (entity: unknown) => internal.isInstanceOf(args[0], entity);
|
|
204
|
+
}
|
|
205
|
+
return internal.isInstanceOf(args[0], args[1]);
|
|
206
|
+
}) as any;
|
|
207
|
+
|
|
181
208
|
/**
|
|
182
209
|
* Type guard for relations.
|
|
183
210
|
* Returns true for both reactive relations and relation snapshots.
|
|
@@ -203,29 +230,29 @@ export const isSnapshot = (value: unknown): value is Snapshot => {
|
|
|
203
230
|
};
|
|
204
231
|
|
|
205
232
|
/**
|
|
206
|
-
* @returns Relation source
|
|
233
|
+
* @returns Relation source URI.
|
|
207
234
|
* Accepts both reactive relations and snapshots.
|
|
208
235
|
* @throws If the object is not a relation.
|
|
209
236
|
*/
|
|
210
|
-
export const
|
|
237
|
+
export const getSourceURI = (value: Unknown | Snapshot): EID.EID => {
|
|
211
238
|
assertArgument(isRelation(value), 'Expected a relation');
|
|
212
239
|
assumeType<internal.InternalObjectProps>(value);
|
|
213
|
-
const
|
|
214
|
-
invariant(
|
|
215
|
-
return
|
|
240
|
+
const uri = (value as internal.InternalObjectProps)[internal.RelationSourceDXNId];
|
|
241
|
+
invariant(EID.isEID(uri));
|
|
242
|
+
return uri;
|
|
216
243
|
};
|
|
217
244
|
|
|
218
245
|
/**
|
|
219
|
-
* @returns Relation target
|
|
246
|
+
* @returns Relation target URI.
|
|
220
247
|
* Accepts both reactive relations and snapshots.
|
|
221
248
|
* @throws If the object is not a relation.
|
|
222
249
|
*/
|
|
223
|
-
export const
|
|
250
|
+
export const getTargetURI = (value: Unknown | Snapshot): EID.EID => {
|
|
224
251
|
assertArgument(isRelation(value), 'Expected a relation');
|
|
225
252
|
assumeType<internal.InternalObjectProps>(value);
|
|
226
|
-
const
|
|
227
|
-
invariant(
|
|
228
|
-
return
|
|
253
|
+
const uri = (value as internal.InternalObjectProps)[internal.RelationTargetDXNId];
|
|
254
|
+
invariant(EID.isEID(uri));
|
|
255
|
+
return uri;
|
|
229
256
|
};
|
|
230
257
|
|
|
231
258
|
/**
|
|
@@ -237,7 +264,9 @@ export const getSource = <T extends Unknown | Snapshot>(relation: T): SourceOf<T
|
|
|
237
264
|
assertArgument(isRelation(relation), 'Expected a relation');
|
|
238
265
|
assumeType<internal.InternalObjectProps>(relation);
|
|
239
266
|
const obj = (relation as internal.InternalObjectProps)[internal.RelationSourceId];
|
|
240
|
-
|
|
267
|
+
if (obj === undefined) {
|
|
268
|
+
throw new Error(`Relation source could not be resolved.`);
|
|
269
|
+
}
|
|
241
270
|
return obj as SourceOf<T>;
|
|
242
271
|
};
|
|
243
272
|
|
|
@@ -250,7 +279,9 @@ export const getTarget = <T extends Unknown | Snapshot>(relation: T): TargetOf<T
|
|
|
250
279
|
assertArgument(isRelation(relation), 'Expected a relation');
|
|
251
280
|
assumeType<internal.InternalObjectProps>(relation);
|
|
252
281
|
const obj = (relation as internal.InternalObjectProps)[internal.RelationTargetId];
|
|
253
|
-
|
|
282
|
+
if (obj === undefined) {
|
|
283
|
+
throw new Error(`Relation target could not be resolved.`);
|
|
284
|
+
}
|
|
254
285
|
return obj as TargetOf<T>;
|
|
255
286
|
};
|
|
256
287
|
|
|
@@ -260,7 +291,7 @@ export const getTarget = <T extends Unknown | Snapshot>(relation: T): TargetOf<T
|
|
|
260
291
|
|
|
261
292
|
/**
|
|
262
293
|
* Makes all properties mutable recursively.
|
|
263
|
-
* Used to provide a mutable view of a relation within `Relation.
|
|
294
|
+
* Used to provide a mutable view of a relation within `Relation.update`.
|
|
264
295
|
*/
|
|
265
296
|
export type Mutable<T> = internal.Mutable<T>;
|
|
266
297
|
|
|
@@ -268,10 +299,10 @@ export type Mutable<T> = internal.Mutable<T>;
|
|
|
268
299
|
* Perform mutations on an echo relation within a controlled context.
|
|
269
300
|
*
|
|
270
301
|
* All mutations within the callback are batched and trigger a single notification
|
|
271
|
-
* when the callback completes. Direct mutations outside of `Relation.
|
|
302
|
+
* when the callback completes. Direct mutations outside of `Relation.update` will throw
|
|
272
303
|
* an error for echo relations.
|
|
273
304
|
*
|
|
274
|
-
* @param relation - The echo relation to mutate. Use `Obj.
|
|
305
|
+
* @param relation - The echo relation to mutate. Use `Obj.update` for objects.
|
|
275
306
|
* @param callback - The callback that performs mutations on the relation.
|
|
276
307
|
*
|
|
277
308
|
* @example
|
|
@@ -282,15 +313,15 @@ export type Mutable<T> = internal.Mutable<T>;
|
|
|
282
313
|
* role: 'Engineer',
|
|
283
314
|
* });
|
|
284
315
|
*
|
|
285
|
-
* // Mutate within Relation.
|
|
286
|
-
* Relation.
|
|
287
|
-
*
|
|
316
|
+
* // Mutate within Relation.update
|
|
317
|
+
* Relation.update(worksFor, (obj) => {
|
|
318
|
+
* obj.role = 'Senior Engineer';
|
|
288
319
|
* });
|
|
289
320
|
* ```
|
|
290
321
|
*
|
|
291
|
-
* Note: Only accepts relations. Use `Obj.
|
|
322
|
+
* Note: Only accepts relations. Use `Obj.update` for objects.
|
|
292
323
|
*/
|
|
293
|
-
export const
|
|
324
|
+
export const update = <T extends Unknown>(relation: T, callback: internal.ChangeCallback<T>): void => {
|
|
294
325
|
internal.change(relation, callback);
|
|
295
326
|
};
|
|
296
327
|
|
|
@@ -333,7 +364,7 @@ export const getValue = (rel: Unknown | Snapshot, path: readonly (string | numbe
|
|
|
333
364
|
|
|
334
365
|
/**
|
|
335
366
|
* Set a deeply nested property on a relation.
|
|
336
|
-
* Must be called within a `Relation.
|
|
367
|
+
* Must be called within a `Relation.update` callback.
|
|
337
368
|
*
|
|
338
369
|
* NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
|
|
339
370
|
* parameters, so there is no compile-time error. Enforcement is runtime-only.
|
|
@@ -346,21 +377,27 @@ export const setValue: (rel: Mutable<Unknown>, path: readonly (string | number)[
|
|
|
346
377
|
//
|
|
347
378
|
|
|
348
379
|
/**
|
|
349
|
-
* Get the
|
|
350
|
-
*
|
|
380
|
+
* Get the canonical URI of the relation. Returns `URI.URI` — today always an EID,
|
|
381
|
+
* but future entity kinds may surface other URI schemes; narrow with `EID.parse(uri)`
|
|
382
|
+
* or `DXN.tryMake(uri)` at the point of use. Accepts both reactive relations and snapshots.
|
|
351
383
|
*/
|
|
352
|
-
export const
|
|
384
|
+
export const getURI = (entity: Unknown | Snapshot): URI.URI => internal.getUri(entity);
|
|
353
385
|
|
|
354
386
|
/**
|
|
355
387
|
* @returns The DXN of the relation's type.
|
|
356
388
|
*/
|
|
357
|
-
export const
|
|
389
|
+
export const getTypeURI: (obj: internal.AnyProperties) => URI.URI | undefined = internal.getTypeURI;
|
|
358
390
|
|
|
359
391
|
/**
|
|
360
|
-
* Get the
|
|
361
|
-
*
|
|
392
|
+
* Get the type entity (`Type.AnyRelation`) the relation was created from.
|
|
393
|
+
*
|
|
394
|
+
* Returns `undefined` when the relation's type isn't registered in this
|
|
395
|
+
* runtime (e.g. a freshly deserialized snapshot whose type entity hasn't been
|
|
396
|
+
* wired up yet, or a relation loaded from storage before its schema is known).
|
|
397
|
+
* To get the Effect Schema from the returned entity, use `Type.getSchema(...)`.
|
|
362
398
|
*/
|
|
363
|
-
export const
|
|
399
|
+
export const getType = (relation: Unknown | Snapshot): Type.AnyRelation | undefined =>
|
|
400
|
+
internal.getType(relation) as Type.AnyRelation | undefined;
|
|
364
401
|
|
|
365
402
|
/**
|
|
366
403
|
* @returns The typename of the relation's type.
|
|
@@ -390,18 +427,18 @@ export const getDatabase = (entity: Unknown | Snapshot): Database.Database | und
|
|
|
390
427
|
export const Meta = internal.MetaId;
|
|
391
428
|
|
|
392
429
|
/**
|
|
393
|
-
* Deeply read-only version of
|
|
430
|
+
* Deeply read-only version of EntityMeta.
|
|
394
431
|
*/
|
|
395
432
|
export type ReadonlyMeta = internal.ReadonlyMeta;
|
|
396
433
|
|
|
397
434
|
/**
|
|
398
|
-
* Mutable meta type returned by `Relation.getMeta` inside a `Relation.
|
|
435
|
+
* Mutable meta type returned by `Relation.getMeta` inside a `Relation.update` callback.
|
|
399
436
|
*/
|
|
400
437
|
export type Meta = internal.Meta;
|
|
401
438
|
|
|
402
439
|
/**
|
|
403
440
|
* Get the metadata for a relation.
|
|
404
|
-
* Returns mutable meta when passed a mutable relation (inside `Relation.
|
|
441
|
+
* Returns mutable meta when passed a mutable relation (inside `Relation.update` callback).
|
|
405
442
|
* Returns read-only meta when passed a regular relation or snapshot.
|
|
406
443
|
*/
|
|
407
444
|
// TODO(wittjosiah): When passed a Snapshot, should return a snapshot of meta, not the live meta proxy.
|
|
@@ -419,7 +456,7 @@ export const getKeys = (entity: Unknown | Snapshot, source: string): ForeignKey[
|
|
|
419
456
|
|
|
420
457
|
/**
|
|
421
458
|
* Delete all keys from the relation for the specified source.
|
|
422
|
-
* Must be called within a `Relation.
|
|
459
|
+
* Must be called within a `Relation.update` callback.
|
|
423
460
|
*
|
|
424
461
|
* NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
|
|
425
462
|
* parameters, so there is no compile-time error. Enforcement is runtime-only.
|
|
@@ -428,21 +465,21 @@ export const deleteKeys = (entity: Mutable<Unknown>, source: string): void => in
|
|
|
428
465
|
|
|
429
466
|
/**
|
|
430
467
|
* Add a tag to the relation.
|
|
431
|
-
* Must be called within a `Relation.
|
|
468
|
+
* Must be called within a `Relation.update` callback.
|
|
432
469
|
*
|
|
433
470
|
* NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
|
|
434
471
|
* parameters, so there is no compile-time error. Enforcement is runtime-only.
|
|
435
472
|
*/
|
|
436
|
-
export const addTag = (entity: Mutable<Unknown>, tag:
|
|
473
|
+
export const addTag = (entity: Mutable<Unknown>, tag: Ref.Ref<Tag.Tag>): void => internal.addTag(entity, tag);
|
|
437
474
|
|
|
438
475
|
/**
|
|
439
476
|
* Remove a tag from the relation.
|
|
440
|
-
* Must be called within a `Relation.
|
|
477
|
+
* Must be called within a `Relation.update` callback.
|
|
441
478
|
*
|
|
442
479
|
* NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
|
|
443
480
|
* parameters, so there is no compile-time error. Enforcement is runtime-only.
|
|
444
481
|
*/
|
|
445
|
-
export const removeTag = (entity: Mutable<Unknown>, tag:
|
|
482
|
+
export const removeTag = (entity: Mutable<Unknown>, tag: Ref.Ref<Tag.Tag>): void => internal.removeTag(entity, tag);
|
|
446
483
|
|
|
447
484
|
/**
|
|
448
485
|
* Check if the relation is deleted.
|
|
@@ -457,12 +494,16 @@ export const isDeleted = (entity: Unknown | Snapshot): boolean => internal.isDel
|
|
|
457
494
|
/**
|
|
458
495
|
* Get the label of the relation.
|
|
459
496
|
* Accepts both reactive relations and snapshots.
|
|
497
|
+
*
|
|
498
|
+
* @param options.fallback `'typename'` returns the relation's typename when no
|
|
499
|
+
* label is set (e.g. `org.dxos.type.table`).
|
|
460
500
|
*/
|
|
461
|
-
export const getLabel = (entity: Unknown | Snapshot): string | undefined =>
|
|
501
|
+
export const getLabel = (entity: Unknown | Snapshot, options?: internal.GetLabelOptions): string | undefined =>
|
|
502
|
+
internal.getLabel(entity, options);
|
|
462
503
|
|
|
463
504
|
/**
|
|
464
505
|
* Set the label of the relation.
|
|
465
|
-
* Must be called within a `Relation.
|
|
506
|
+
* Must be called within a `Relation.update` callback.
|
|
466
507
|
*
|
|
467
508
|
* NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
|
|
468
509
|
* parameters, so there is no compile-time error. Enforcement is runtime-only.
|
|
@@ -477,7 +518,7 @@ export const getDescription = (entity: Unknown | Snapshot): string | undefined =
|
|
|
477
518
|
|
|
478
519
|
/**
|
|
479
520
|
* Set the description of the relation.
|
|
480
|
-
* Must be called within a `Relation.
|
|
521
|
+
* Must be called within a `Relation.update` callback.
|
|
481
522
|
*
|
|
482
523
|
* NOTE: TypeScript's structural typing allows readonly objects to be passed to `Mutable<T>`
|
|
483
524
|
* parameters, so there is no compile-time error. Enforcement is runtime-only.
|
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(otherSpaceId))); // a specific space
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export const space = (spaceId?: string, options?: { includeAllFeeds?: boolean }): QueryAST.SpaceScope => ({
|
|
22
|
+
_tag: 'space',
|
|
23
|
+
...(spaceId !== undefined ? { spaceId } : {}),
|
|
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 DXN).
|
|
46
|
+
*/
|
|
47
|
+
export const feed = (feedUri: string): QueryAST.FeedScope => ({
|
|
48
|
+
_tag: 'feed',
|
|
49
|
+
feedUri,
|
|
50
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Schema from 'effect/Schema';
|
|
6
|
+
import { describe, expect, test } from 'vitest';
|
|
7
|
+
|
|
8
|
+
import { DXN } from '@dxos/keys';
|
|
9
|
+
|
|
10
|
+
import * as Obj from './Obj';
|
|
11
|
+
import * as StateMap from './StateMap';
|
|
12
|
+
import * as Type from './Type';
|
|
13
|
+
|
|
14
|
+
/** Per-item state stored in the side-map (the non-tag metadata for a feed item). */
|
|
15
|
+
const PostState = Schema.Struct({
|
|
16
|
+
readAt: Schema.optional(Schema.String),
|
|
17
|
+
imageUrl: Schema.optional(Schema.String),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
/** A host object carrying a per-object state side-map alongside (a notional feed of) items. */
|
|
21
|
+
const Host = Schema.Struct({
|
|
22
|
+
postState: StateMap.field(PostState),
|
|
23
|
+
}).pipe(Type.makeObject(DXN.make('org.dxos.test.StateMapHost', '0.1.0')));
|
|
24
|
+
|
|
25
|
+
describe('StateMap', () => {
|
|
26
|
+
test('patches, reads, and removes per-object state', () => {
|
|
27
|
+
const host = Obj.make(Host, {});
|
|
28
|
+
const state = StateMap.bind(host, 'postState');
|
|
29
|
+
|
|
30
|
+
const itemA = 'item-a';
|
|
31
|
+
const itemB = 'item-b';
|
|
32
|
+
|
|
33
|
+
// Absent → empty object (no ?-chains at call sites).
|
|
34
|
+
expect(state.get(itemA)).toEqual({});
|
|
35
|
+
|
|
36
|
+
// Patch creates, then shallow-merges.
|
|
37
|
+
state.patch(itemA, { readAt: 't1' });
|
|
38
|
+
expect(state.get(itemA)).toEqual({ readAt: 't1' });
|
|
39
|
+
state.patch(itemA, { imageUrl: 'u1' });
|
|
40
|
+
expect(state.get(itemA)).toEqual({ readAt: 't1', imageUrl: 'u1' });
|
|
41
|
+
// Overwrite a field.
|
|
42
|
+
state.patch(itemA, { readAt: 't2' });
|
|
43
|
+
expect(state.get(itemA)).toEqual({ readAt: 't2', imageUrl: 'u1' });
|
|
44
|
+
|
|
45
|
+
state.patch(itemB, { imageUrl: 'u2' });
|
|
46
|
+
|
|
47
|
+
// Predicate-filtered ids.
|
|
48
|
+
expect(state.ids().sort()).toEqual([itemA, itemB]);
|
|
49
|
+
expect(state.ids((value) => Boolean(value.readAt))).toEqual([itemA]);
|
|
50
|
+
|
|
51
|
+
// Remove drops the entry.
|
|
52
|
+
state.remove(itemA);
|
|
53
|
+
expect(state.get(itemA)).toEqual({});
|
|
54
|
+
expect(state.ids()).toEqual([itemB]);
|
|
55
|
+
});
|
|
56
|
+
});
|
package/src/StateMap.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
// @import-as-namespace
|
|
6
|
+
|
|
7
|
+
import * as Schema from 'effect/Schema';
|
|
8
|
+
|
|
9
|
+
import { FormInputAnnotation } from './internal';
|
|
10
|
+
import * as Obj from './Obj';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A per-object state side-map: an in-document `Record<objectId, S>` holding small mutable metadata
|
|
14
|
+
* for each object, keyed by object id.
|
|
15
|
+
*
|
|
16
|
+
* The companion to immutable feed/queue objects: the objects are immutable, so their mutable
|
|
17
|
+
* per-item state (read-marker, hero image, snippet, …) lives here on a host object. Use this for
|
|
18
|
+
* non-tag metadata; boolean labels (starred, archived) belong in the tag model ({@link TagIndex} /
|
|
19
|
+
* {@link Tagging}) so they share the space-wide `Tag` registry.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/** Read/write accessor over a host object's state side-map field, bound to a single field key. */
|
|
23
|
+
export interface Accessor<S extends object> {
|
|
24
|
+
/** All object ids with an entry, optionally filtered by a predicate over their state. */
|
|
25
|
+
ids(predicate?: (state: Partial<S>, id: string) => boolean): string[];
|
|
26
|
+
/** The entry for an object id; `{}` when absent (so call sites read fields without `?` chains). */
|
|
27
|
+
get(id: string): Partial<S>;
|
|
28
|
+
/** All `[id, state]` entries. */
|
|
29
|
+
entries(): Array<[string, Partial<S>]>;
|
|
30
|
+
/** Shallow-merges a patch into an object's entry, creating it when absent. */
|
|
31
|
+
patch(id: string, patch: Partial<S>): void;
|
|
32
|
+
/** Removes an object's entry. */
|
|
33
|
+
remove(id: string): void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Schema fragment for a state side-map field. Splice into a host Struct. Optional record, hidden
|
|
38
|
+
* from forms. Keyed by object id; the value is the per-object state struct `S`.
|
|
39
|
+
*/
|
|
40
|
+
export const field = <S, I>(value: Schema.Schema<S, I>) =>
|
|
41
|
+
Schema.Record({ key: Schema.String, value }).pipe(FormInputAnnotation.set(false), Schema.optional);
|
|
42
|
+
|
|
43
|
+
/** Binds an {@link Accessor} over `host[key]`; all mutations go through `Obj.update`. */
|
|
44
|
+
export const bind = <S extends object = Record<string, unknown>>(host: Obj.Any, key: string): Accessor<S> => {
|
|
45
|
+
type Entry = Partial<S>;
|
|
46
|
+
|
|
47
|
+
// The field is addressed by a runtime key, so the ECHO object is viewed as a keyed record — a
|
|
48
|
+
// deliberate type-system boundary (dynamic field access — the field name is a parameter).
|
|
49
|
+
const asView = (obj: Obj.Any) => obj as unknown as Record<string, Record<string, Entry> | undefined>;
|
|
50
|
+
const read = (): Record<string, Entry> => asView(host)[key] ?? {};
|
|
51
|
+
|
|
52
|
+
// Mutate the live typed record in place (do NOT reassign the whole tree); assigning a detached
|
|
53
|
+
// plain object tree bypasses ECHO's schema-aware conversion. Mutating the typed proxy preserves it.
|
|
54
|
+
const write = (mutate: (record: Record<string, Entry>) => void): void => {
|
|
55
|
+
Obj.update(host, (host) => {
|
|
56
|
+
const view = asView(host);
|
|
57
|
+
if (view[key] === undefined) {
|
|
58
|
+
view[key] = {};
|
|
59
|
+
}
|
|
60
|
+
// Re-read after assignment: the assignment expression yields the plain RHS, not the
|
|
61
|
+
// ECHO-backed reactive record, so mutating that would not persist.
|
|
62
|
+
mutate(view[key]!);
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Existence check via `Object.keys` — ECHO's reactive record proxy auto-vivifies missing keys on
|
|
67
|
+
// direct access, so `record[id]` is not reliably `undefined` for absent ids.
|
|
68
|
+
const has = (record: Record<string, Entry>, id: string): boolean => Object.keys(record).includes(id);
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
ids: (predicate) => {
|
|
72
|
+
const record = read();
|
|
73
|
+
const keys = Object.keys(record);
|
|
74
|
+
return predicate ? keys.filter((id) => predicate(record[id], id)) : keys;
|
|
75
|
+
},
|
|
76
|
+
get: (id) => {
|
|
77
|
+
const record = read();
|
|
78
|
+
return has(record, id) ? record[id] : {};
|
|
79
|
+
},
|
|
80
|
+
entries: () => {
|
|
81
|
+
const record = read();
|
|
82
|
+
return Object.keys(record).map((id) => [id, record[id]]);
|
|
83
|
+
},
|
|
84
|
+
patch: (id, patch) =>
|
|
85
|
+
write((record) => {
|
|
86
|
+
if (!has(record, id)) {
|
|
87
|
+
record[id] = { ...patch };
|
|
88
|
+
} else {
|
|
89
|
+
Object.assign(record[id], patch);
|
|
90
|
+
}
|
|
91
|
+
}),
|
|
92
|
+
remove: (id) =>
|
|
93
|
+
write((record) => {
|
|
94
|
+
if (has(record, id)) {
|
|
95
|
+
delete record[id];
|
|
96
|
+
}
|
|
97
|
+
}),
|
|
98
|
+
};
|
|
99
|
+
};
|