@dxos/echo 0.8.4-main.d05539e30a → 0.8.4-main.d9fc60f731
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/lib/neutral/Annotation.mjs +27 -6
- package/dist/lib/neutral/Database.mjs +6 -11
- package/dist/lib/neutral/Entity.mjs +25 -16
- package/dist/lib/neutral/Err.mjs +3 -3
- package/dist/lib/neutral/Feed.mjs +19 -17
- package/dist/lib/neutral/Filter.mjs +13 -13
- 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 +21 -18
- package/dist/lib/neutral/Query.mjs +17 -17
- package/dist/lib/neutral/QueryResult.mjs +1 -1
- package/dist/lib/neutral/Ref.mjs +10 -11
- package/dist/lib/neutral/Registry.mjs +14 -0
- package/dist/lib/neutral/Relation.mjs +24 -23
- package/dist/lib/neutral/Scope.mjs +12 -0
- package/dist/lib/neutral/Tag.mjs +17 -14
- 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-PT37DG2F.mjs → chunk-4SFPZJVA.mjs} +82 -74
- package/dist/lib/neutral/chunk-4SFPZJVA.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-APHSOTIX.mjs → chunk-4Z6GET2X.mjs} +3 -3
- package/dist/lib/neutral/{chunk-APHSOTIX.mjs.map → chunk-4Z6GET2X.mjs.map} +2 -2
- package/dist/lib/neutral/{chunk-7RVZT53K.mjs → chunk-7LOUAPYZ.mjs} +9 -5
- package/dist/lib/neutral/chunk-7LOUAPYZ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-BMB7IHGB.mjs → chunk-7OAFN3OX.mjs} +70 -57
- package/dist/lib/neutral/chunk-7OAFN3OX.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-MLS7U7AT.mjs → chunk-7PRCIDHH.mjs} +41 -28
- package/dist/lib/neutral/chunk-7PRCIDHH.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-ZISMEVKD.mjs → chunk-BBFJWWAV.mjs} +6 -6
- package/dist/lib/neutral/chunk-BBFJWWAV.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-ZFACXBY6.mjs → chunk-BDQGMDIX.mjs} +30 -34
- 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-V72DY6LU.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-QRZ2I3ZM.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-N7VOEPSV.mjs → chunk-J3MNM65T.mjs} +9 -9
- 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-N4B7FHQT.mjs → chunk-O6BH7EPN.mjs} +30 -3
- package/dist/lib/neutral/chunk-O6BH7EPN.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-Q7ZL2P5H.mjs → chunk-OIYW7R2G.mjs} +62 -46
- package/dist/lib/neutral/chunk-OIYW7R2G.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-G54OX4IX.mjs → chunk-OYUG4FHF.mjs} +527 -847
- package/dist/lib/neutral/chunk-OYUG4FHF.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-J54QMAKF.mjs → chunk-Q5FKCVBC.mjs} +64 -59
- package/dist/lib/neutral/chunk-Q5FKCVBC.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-FIWO2FZK.mjs → chunk-Q62IHV2N.mjs} +12 -7
- package/dist/lib/neutral/chunk-Q62IHV2N.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-SCPFDS2E.mjs → chunk-QVJDDG44.mjs} +65 -34
- package/dist/lib/neutral/chunk-QVJDDG44.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-TRPZU2HV.mjs → chunk-TFEWTY5A.mjs} +155 -129
- package/dist/lib/neutral/chunk-TFEWTY5A.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-44HT3MEC.mjs → chunk-VKWOFXT2.mjs} +22 -2
- package/dist/lib/neutral/{chunk-44HT3MEC.mjs.map → chunk-VKWOFXT2.mjs.map} +1 -1
- package/dist/lib/neutral/{chunk-APJKDGFL.mjs → chunk-ZACMEAYV.mjs} +24 -24
- package/dist/lib/neutral/chunk-ZACMEAYV.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +50 -40
- package/dist/lib/neutral/internal/index.mjs +125 -64
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/testing/index.mjs +88 -99
- 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 +50 -30
- 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 +89 -19
- package/dist/types/src/Entity.d.ts.map +1 -1
- package/dist/types/src/Err.d.ts +9 -9
- package/dist/types/src/Err.d.ts.map +1 -1
- package/dist/types/src/Feed.d.ts +35 -12
- package/dist/types/src/Feed.d.ts.map +1 -1
- package/dist/types/src/Filter.d.ts +21 -8
- package/dist/types/src/Filter.d.ts.map +1 -1
- package/dist/types/src/Hypergraph.d.ts +13 -8
- package/dist/types/src/Hypergraph.d.ts.map +1 -1
- package/dist/types/src/Json.d.ts.map +1 -1
- package/dist/types/src/JsonSchema.d.ts +1 -1
- 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 +15 -12
- package/dist/types/src/Migration.d.ts.map +1 -1
- package/dist/types/src/Obj.d.ts +69 -40
- package/dist/types/src/Obj.d.ts.map +1 -1
- package/dist/types/src/Query.d.ts +24 -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 -8
- 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 +55 -26
- 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 +19 -3
- 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 +356 -95
- package/dist/types/src/Type.d.ts.map +1 -1
- package/dist/types/src/View.d.ts +1 -4
- package/dist/types/src/View.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +6 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/annotations.d.ts +68 -36
- 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/util.d.ts +13 -4
- 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 +18 -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/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/object.d.ts +3 -1
- package/dist/types/src/internal/Format/object.d.ts.map +1 -1
- package/dist/types/src/internal/JsonSchema/json-schema.d.ts +2 -1
- 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/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/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 +8 -8
- package/dist/types/src/internal/Obj/json-serializer.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.map +1 -1
- package/dist/types/src/internal/Ref/ref-array.d.ts +2 -2
- package/dist/types/src/internal/Ref/ref.d.ts +29 -19
- package/dist/types/src/internal/Ref/ref.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 +11 -8
- package/dist/types/src/internal/common/api/meta.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/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/entity.d.ts +59 -2
- 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 +13 -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/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 +1 -0
- package/dist/types/src/internal/index.d.ts.map +1 -1
- package/dist/types/src/testing/test-schema.d.ts +32 -38
- 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 +21 -23
- package/src/Annotation.test.ts +439 -0
- package/src/Annotation.ts +151 -4
- package/src/Collection.ts +5 -9
- package/src/Database.ts +86 -61
- package/src/Dataset.ts +10 -2
- package/src/Entity.test.ts +116 -6
- package/src/Entity.ts +116 -23
- package/src/Err.ts +4 -4
- package/src/Feed.ts +57 -40
- package/src/Filter.ts +49 -27
- package/src/Hypergraph.ts +13 -8
- package/src/Json.test.ts +4 -4
- package/src/Json.ts +7 -6
- package/src/Key.ts +1 -1
- package/src/Migration.ts +27 -19
- package/src/Obj.test.ts +19 -8
- package/src/Obj.ts +131 -70
- package/src/Query.test.ts +147 -151
- package/src/Query.ts +133 -75
- package/src/QueryResult.ts +11 -0
- package/src/Ref.ts +21 -5
- package/src/Registry.ts +155 -0
- package/src/Relation.test.ts +10 -10
- package/src/Relation.ts +89 -52
- 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 +601 -131
- package/src/View.ts +10 -19
- package/src/index.ts +6 -4
- package/src/internal/Annotation/annotations.test.ts +31 -11
- package/src/internal/Annotation/annotations.ts +122 -103
- 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/util.ts +17 -8
- package/src/internal/Entity/api.ts +7 -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 +35 -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 +87 -0
- package/src/internal/Entity/util.ts +10 -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.test.ts +54 -140
- package/src/internal/JsonSchema/json-schema.ts +44 -30
- 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 +67 -22
- package/src/internal/Obj/index.ts +0 -1
- package/src/internal/Obj/inspect.ts +4 -3
- package/src/internal/Obj/json-serializer.test.ts +100 -21
- package/src/internal/Obj/json-serializer.ts +93 -38
- package/src/internal/Obj/set-value.test.ts +7 -30
- 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 +14 -11
- package/src/internal/Ref/ref-array.ts +3 -3
- package/src/internal/Ref/ref.test.ts +17 -26
- package/src/internal/Ref/ref.ts +107 -59
- 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 +1 -1
- package/src/internal/common/api/meta.ts +16 -14
- package/src/internal/common/proxy/change.test.ts +35 -27
- package/src/internal/common/proxy/handler.test.ts +1 -1
- package/src/internal/common/proxy/json-serializer.ts +26 -16
- package/src/internal/common/proxy/make-object.ts +43 -20
- package/src/internal/common/proxy/ownership.ts +2 -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 +71 -9
- package/src/internal/common/proxy/typed-object.test.ts +15 -27
- 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 +37 -14
- 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 +5 -0
- package/src/testing/api.test.ts +15 -9
- package/src/testing/test-data.ts +24 -24
- 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-5SL5LDLD.mjs +0 -47
- package/dist/lib/neutral/chunk-5SL5LDLD.mjs.map +0 -7
- package/dist/lib/neutral/chunk-7RVZT53K.mjs.map +0 -7
- package/dist/lib/neutral/chunk-APJKDGFL.mjs.map +0 -7
- package/dist/lib/neutral/chunk-BICZKPQG.mjs +0 -7
- package/dist/lib/neutral/chunk-BICZKPQG.mjs.map +0 -7
- package/dist/lib/neutral/chunk-BMB7IHGB.mjs.map +0 -7
- package/dist/lib/neutral/chunk-FIWO2FZK.mjs.map +0 -7
- package/dist/lib/neutral/chunk-G54OX4IX.mjs.map +0 -7
- package/dist/lib/neutral/chunk-GWFFC34K.mjs +0 -50
- package/dist/lib/neutral/chunk-GWFFC34K.mjs.map +0 -7
- package/dist/lib/neutral/chunk-I2DARWPX.mjs +0 -128
- package/dist/lib/neutral/chunk-I2DARWPX.mjs.map +0 -7
- package/dist/lib/neutral/chunk-J54QMAKF.mjs.map +0 -7
- package/dist/lib/neutral/chunk-MGSQGHOD.mjs +0 -206
- package/dist/lib/neutral/chunk-MGSQGHOD.mjs.map +0 -7
- package/dist/lib/neutral/chunk-MLS7U7AT.mjs.map +0 -7
- package/dist/lib/neutral/chunk-N4B7FHQT.mjs.map +0 -7
- package/dist/lib/neutral/chunk-N7VOEPSV.mjs.map +0 -7
- package/dist/lib/neutral/chunk-PSZBLH53.mjs +0 -81
- package/dist/lib/neutral/chunk-PSZBLH53.mjs.map +0 -7
- package/dist/lib/neutral/chunk-PT37DG2F.mjs.map +0 -7
- package/dist/lib/neutral/chunk-Q2KKKJSV.mjs +0 -56
- package/dist/lib/neutral/chunk-Q2KKKJSV.mjs.map +0 -7
- package/dist/lib/neutral/chunk-Q7ZL2P5H.mjs.map +0 -7
- package/dist/lib/neutral/chunk-SCPFDS2E.mjs.map +0 -7
- package/dist/lib/neutral/chunk-TNBK56IN.mjs +0 -350
- package/dist/lib/neutral/chunk-TNBK56IN.mjs.map +0 -7
- package/dist/lib/neutral/chunk-TRPZU2HV.mjs.map +0 -7
- package/dist/lib/neutral/chunk-V72DY6LU.mjs.map +0 -7
- package/dist/lib/neutral/chunk-ZFACXBY6.mjs.map +0 -7
- package/dist/lib/neutral/chunk-ZISMEVKD.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/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-QRZ2I3ZM.mjs.map → chunk-G6CFWUYH.mjs.map} +0 -0
|
@@ -0,0 +1,57 @@
|
|
|
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 TagIndex from './TagIndex';
|
|
12
|
+
import * as Type from './Type';
|
|
13
|
+
|
|
14
|
+
/** A minimal item standing in for an immutable feed object. */
|
|
15
|
+
const Item = Schema.Struct({
|
|
16
|
+
text: Schema.String,
|
|
17
|
+
}).pipe(Type.makeObject(DXN.make('org.dxos.test.TagIndexItem', '0.1.0')));
|
|
18
|
+
|
|
19
|
+
/** A host object carrying a tag index alongside (a notional feed of) items. */
|
|
20
|
+
const Host = Schema.Struct({
|
|
21
|
+
tags: TagIndex.field(),
|
|
22
|
+
}).pipe(Type.makeObject(DXN.make('org.dxos.test.TagIndexHost', '0.1.0')));
|
|
23
|
+
|
|
24
|
+
describe('TagIndex', () => {
|
|
25
|
+
test('sets, unsets, and inverts feed-object tags', () => {
|
|
26
|
+
const host = Obj.make(Host, {});
|
|
27
|
+
const tags = TagIndex.bind(host, 'tags');
|
|
28
|
+
|
|
29
|
+
const a = Obj.make(Item, { text: 'a' });
|
|
30
|
+
const b = Obj.make(Item, { text: 'b' });
|
|
31
|
+
const urgent = 'dxn:tag:urgent';
|
|
32
|
+
const later = 'dxn:tag:later';
|
|
33
|
+
|
|
34
|
+
tags.setTag(urgent, a.id);
|
|
35
|
+
tags.setTag(urgent, b.id);
|
|
36
|
+
tags.setTag(later, b.id);
|
|
37
|
+
// Idempotent.
|
|
38
|
+
tags.setTag(urgent, a.id);
|
|
39
|
+
|
|
40
|
+
// Filter the feed by tag: tag -> object ids.
|
|
41
|
+
expect([...tags.objects(urgent)]).toEqual([a.id, b.id]);
|
|
42
|
+
expect([...tags.objects(later)]).toEqual([b.id]);
|
|
43
|
+
expect([...tags.objects('dxn:tag:missing')]).toEqual([]);
|
|
44
|
+
|
|
45
|
+
// Inverse: object -> tag ids.
|
|
46
|
+
expect(tags.tags(b.id).sort()).toEqual([later, urgent]);
|
|
47
|
+
expect(tags.tags(a.id)).toEqual([urgent]);
|
|
48
|
+
expect(tags.tagIds().sort()).toEqual([later, urgent]);
|
|
49
|
+
|
|
50
|
+
// Unset prunes the membership; emptying a tag drops the key.
|
|
51
|
+
tags.unsetTag(urgent, a.id);
|
|
52
|
+
expect([...tags.objects(urgent)]).toEqual([b.id]);
|
|
53
|
+
tags.unsetTag(urgent, b.id);
|
|
54
|
+
expect([...tags.objects(urgent)]).toEqual([]);
|
|
55
|
+
expect(tags.tagIds()).toEqual([later]);
|
|
56
|
+
});
|
|
57
|
+
});
|
package/src/TagIndex.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
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
|
+
* An inverse tag index: an in-document `Record<tagId, objectId[]>` mapping a tag id to the ids of
|
|
14
|
+
* the objects carrying that tag.
|
|
15
|
+
*
|
|
16
|
+
* Mutable database objects track their tags in `Obj.getMeta(obj).tags` (an array of tag ids).
|
|
17
|
+
* Immutable feed/queue objects cannot carry their own meta, so this index — managed alongside the
|
|
18
|
+
* feed on its host object — augments that same process for them. Tags are sparse, so keying by tag
|
|
19
|
+
* id (rather than object id) keeps the index small and makes "filter the feed by tag" a single
|
|
20
|
+
* lookup.
|
|
21
|
+
*
|
|
22
|
+
* The tag id is an existing {@link Tag} object's id/URI; labels are never duplicated here — they
|
|
23
|
+
* live on the {@link Tag} object and stay editable in one place.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/** Read/write accessor over a host object's tag-index field, bound to a single field key. */
|
|
27
|
+
export interface Accessor {
|
|
28
|
+
/** All tag ids present in the index. */
|
|
29
|
+
tagIds(): string[];
|
|
30
|
+
/** Object ids carrying the given tag; `[]` when the tag is absent (filter the feed by tag). */
|
|
31
|
+
objects(tagId: string): readonly string[];
|
|
32
|
+
/** Inverse lookup: the tag ids applied to the given object id. */
|
|
33
|
+
tags(objectId: string): string[];
|
|
34
|
+
/** Applies a tag to an object (creating the tag entry when absent); idempotent. */
|
|
35
|
+
setTag(tagId: string, objectId: string): void;
|
|
36
|
+
/** Removes a tag from an object, pruning the tag entry when it empties. */
|
|
37
|
+
unsetTag(tagId: string, objectId: string): void;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Schema fragment for a tag-index field. Splice into a host Struct. Optional record, hidden from
|
|
42
|
+
* forms. Keyed by tag id; the value is the array of object ids carrying that tag.
|
|
43
|
+
*/
|
|
44
|
+
export const field = () =>
|
|
45
|
+
Schema.Record({ key: Schema.String, value: Schema.Array(Obj.ID) }).pipe(
|
|
46
|
+
FormInputAnnotation.set(false),
|
|
47
|
+
Schema.optional,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
/** Binds an {@link Accessor} over `host[key]`; all mutations go through `Obj.update`. */
|
|
51
|
+
export const bind = (host: Obj.Any, key: string): Accessor => {
|
|
52
|
+
type Record_ = Record<string, string[]>;
|
|
53
|
+
|
|
54
|
+
// The field is addressed by a runtime key, so the ECHO object is viewed as a keyed record — a
|
|
55
|
+
// deliberate type-system boundary (dynamic field access — the field name is a parameter).
|
|
56
|
+
const asView = (obj: Obj.Any) => obj as unknown as Record<string, Record_ | undefined>;
|
|
57
|
+
const read = (): Record_ => asView(host)[key] ?? {};
|
|
58
|
+
|
|
59
|
+
// Mutate the live typed record in place (do NOT reassign the whole tree); assigning a detached
|
|
60
|
+
// plain object tree bypasses ECHO's schema-aware conversion and stores arrays as numeric-keyed
|
|
61
|
+
// objects. Mutating the typed proxy (and assigning real arrays to its values) preserves arrays.
|
|
62
|
+
const write = (mutate: (record: Record_) => void): void => {
|
|
63
|
+
Obj.update(host, (host) => {
|
|
64
|
+
const view = asView(host);
|
|
65
|
+
if (view[key] === undefined) {
|
|
66
|
+
view[key] = {};
|
|
67
|
+
}
|
|
68
|
+
// Re-read after assignment: the assignment expression yields the plain RHS, not the
|
|
69
|
+
// ECHO-backed reactive record, so mutating that would not persist.
|
|
70
|
+
mutate(view[key]!);
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// Existence check via `Object.keys` — ECHO's reactive record proxy auto-vivifies missing keys on
|
|
75
|
+
// direct access, so `record[tagId]` is not reliably `undefined` for absent tags.
|
|
76
|
+
const has = (record: Record_, tagId: string): boolean => Object.keys(record).includes(tagId);
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
tagIds: () => Object.keys(read()),
|
|
80
|
+
objects: (tagId) => {
|
|
81
|
+
const record = read();
|
|
82
|
+
return has(record, tagId) ? record[tagId] : [];
|
|
83
|
+
},
|
|
84
|
+
tags: (objectId) => {
|
|
85
|
+
const record = read();
|
|
86
|
+
return Object.keys(record).filter((tagId) => record[tagId].includes(objectId));
|
|
87
|
+
},
|
|
88
|
+
setTag: (tagId, objectId) =>
|
|
89
|
+
write((record) => {
|
|
90
|
+
// Use `has` (not `record[tagId]`) for absence — the proxy auto-vivifies missing keys.
|
|
91
|
+
if (!has(record, tagId)) {
|
|
92
|
+
record[tagId] = [objectId];
|
|
93
|
+
} else if (!record[tagId].includes(objectId)) {
|
|
94
|
+
record[tagId] = [...record[tagId], objectId];
|
|
95
|
+
}
|
|
96
|
+
}),
|
|
97
|
+
unsetTag: (tagId, objectId) =>
|
|
98
|
+
write((record) => {
|
|
99
|
+
if (!has(record, tagId)) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const next = record[tagId].filter((existing) => existing !== objectId);
|
|
103
|
+
if (next.length === 0) {
|
|
104
|
+
delete record[tagId];
|
|
105
|
+
} else {
|
|
106
|
+
record[tagId] = next;
|
|
107
|
+
}
|
|
108
|
+
}),
|
|
109
|
+
};
|
|
110
|
+
};
|
package/src/Tagging.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
// @import-as-namespace
|
|
6
|
+
|
|
7
|
+
import { EID, URI } from '@dxos/keys';
|
|
8
|
+
|
|
9
|
+
import type * as Database from './Database';
|
|
10
|
+
import * as Obj from './Obj';
|
|
11
|
+
import * as Ref from './Ref';
|
|
12
|
+
import type * as Tag from './Tag';
|
|
13
|
+
import * as TagIndex from './TagIndex';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Unified tag handling for objects whether their tags live on the object (mutable database objects)
|
|
17
|
+
* or alongside it (immutable feed/queue objects).
|
|
18
|
+
*
|
|
19
|
+
* - Mutable database objects track their tags in `Obj.getMeta(obj).tags` (an array of `Ref<Tag>`).
|
|
20
|
+
* - Immutable feed objects can't carry their own meta, so their tags live in a {@link TagIndex} on
|
|
21
|
+
* a host object; pass that host via {@link Options.host}.
|
|
22
|
+
*
|
|
23
|
+
* Either way the tag id is an existing {@link Tag} object's id/URI, so the same tag applies across
|
|
24
|
+
* mutable and immutable objects and its label is resolved (and edited) in one place. This API works
|
|
25
|
+
* in terms of those URI tag ids; on the mutable path it converts to/from the stored `Ref<Tag>`.
|
|
26
|
+
*/
|
|
27
|
+
export interface Options {
|
|
28
|
+
/** Host object whose tag index holds tags for the (immutable) object. Omit for mutable objects. */
|
|
29
|
+
host?: Obj.Any;
|
|
30
|
+
/** Tag-index field name on the host (default `tags`). */
|
|
31
|
+
key?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const DEFAULT_KEY = 'tags';
|
|
35
|
+
|
|
36
|
+
/** Returns the tag ids (URIs) applied to an object. */
|
|
37
|
+
export const get = (object: Obj.Any, options: Options = {}): string[] => {
|
|
38
|
+
const { host, key = DEFAULT_KEY } = options;
|
|
39
|
+
if (host) {
|
|
40
|
+
return TagIndex.bind(host, key).tags(object.id);
|
|
41
|
+
}
|
|
42
|
+
return Obj.getMeta(object).tags.map((tag) => tag.uri);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/** Applies a tag (by id/URI) to an object (idempotent). */
|
|
46
|
+
export const set = (object: Obj.Any, tagId: string, options: Options = {}): void => {
|
|
47
|
+
const { host, key = DEFAULT_KEY } = options;
|
|
48
|
+
if (host) {
|
|
49
|
+
TagIndex.bind(host, key).setTag(tagId, object.id);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// Stored tag refs are canonical EIDs (read-time upgrade normalizes legacy DXN ids); normalize the
|
|
53
|
+
// incoming id the same way so dedupe compares like-for-like.
|
|
54
|
+
const id = EID.tryParse(tagId) ?? tagId;
|
|
55
|
+
Obj.update(object, (object) => {
|
|
56
|
+
const meta = Obj.getMeta(object);
|
|
57
|
+
if (!meta.tags.some((tag) => tag.uri === id)) {
|
|
58
|
+
meta.tags.push(Ref.fromURI(URI.make(id)));
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/** Removes a tag (by id/URI) from an object. No-op when not present. */
|
|
64
|
+
export const unset = (object: Obj.Any, tagId: string, options: Options = {}): void => {
|
|
65
|
+
const { host, key = DEFAULT_KEY } = options;
|
|
66
|
+
if (host) {
|
|
67
|
+
TagIndex.bind(host, key).unsetTag(tagId, object.id);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const id = EID.tryParse(tagId) ?? tagId;
|
|
71
|
+
Obj.update(object, (object) => {
|
|
72
|
+
const meta = Obj.getMeta(object);
|
|
73
|
+
for (let i = meta.tags.length - 1; i >= 0; i--) {
|
|
74
|
+
if (meta.tags[i].uri === id) {
|
|
75
|
+
meta.tags.splice(i, 1);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/** Resolves tag ids (URIs) to {@link Tag} object refs via the database. */
|
|
82
|
+
export const resolve = (db: Pick<Database.Database, 'makeRef'>, tagIds: readonly string[]): Ref.Ref<Tag.Tag>[] =>
|
|
83
|
+
tagIds.map((id) => db.makeRef<Tag.Tag>(URI.make(id)));
|
package/src/Type.test.ts
CHANGED
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
import * as Schema from 'effect/Schema';
|
|
6
6
|
import { describe, test } from 'vitest';
|
|
7
7
|
|
|
8
|
+
import { DXN, EntityId } from '@dxos/keys';
|
|
9
|
+
|
|
10
|
+
import * as Entity from './Entity';
|
|
11
|
+
import * as JsonSchema from './JsonSchema';
|
|
8
12
|
import * as Obj from './Obj';
|
|
9
13
|
import * as Relation from './Relation';
|
|
10
14
|
import { TestSchema } from './testing';
|
|
@@ -12,16 +16,9 @@ import * as Type from './Type';
|
|
|
12
16
|
|
|
13
17
|
describe('Type', () => {
|
|
14
18
|
describe('Obj.Unknown schema', () => {
|
|
15
|
-
test('has SchemaKindId for schema type checking', ({ expect }) => {
|
|
16
|
-
// Type.isObjectSchema uses SchemaKindId to check if a schema is an object schema.
|
|
17
|
-
expect(Type.isObjectSchema(Obj.Unknown)).toBe(true);
|
|
18
|
-
expect(Type.isObjectSchema(TestSchema.Person)).toBe(true);
|
|
19
|
-
expect(Type.isObjectSchema(Relation.Unknown)).toBe(false);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
19
|
test('Schema.is validates structural compatibility only', ({ expect }) => {
|
|
23
|
-
// Schema.is does structural validation (has id field).
|
|
24
|
-
//
|
|
20
|
+
// Schema.is does structural validation (has id field). `Obj.Unknown` IS
|
|
21
|
+
// a raw Effect Schema (branded with EchoSchemaKind), so pass it directly.
|
|
25
22
|
expect(Schema.is(Obj.Unknown)({ id: 'plain-object' })).toBe(true);
|
|
26
23
|
const obj = Obj.make(TestSchema.Person, { name: 'Test' });
|
|
27
24
|
expect(Schema.is(Obj.Unknown)(obj)).toBe(true);
|
|
@@ -29,16 +26,9 @@ describe('Type', () => {
|
|
|
29
26
|
});
|
|
30
27
|
|
|
31
28
|
describe('Relation.Unknown schema', () => {
|
|
32
|
-
test('has SchemaKindId for schema type checking', ({ expect }) => {
|
|
33
|
-
// Type.isRelationSchema uses SchemaKindId to check if a schema is a relation schema.
|
|
34
|
-
expect(Type.isRelationSchema(Relation.Unknown)).toBe(true);
|
|
35
|
-
expect(Type.isRelationSchema(TestSchema.HasManager)).toBe(true);
|
|
36
|
-
expect(Type.isRelationSchema(Obj.Unknown)).toBe(false);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
29
|
test('Schema.is validates structural compatibility only', ({ expect }) => {
|
|
40
|
-
// Schema.is does structural validation (has id field).
|
|
41
|
-
//
|
|
30
|
+
// Schema.is does structural validation (has id field). `Relation.Unknown`
|
|
31
|
+
// IS a raw Effect Schema (branded with EchoSchemaKind), so pass it directly.
|
|
42
32
|
expect(Schema.is(Relation.Unknown)({ id: 'plain-object' })).toBe(true);
|
|
43
33
|
const obj1 = Obj.make(TestSchema.Person, { name: 'Alice' });
|
|
44
34
|
const obj2 = Obj.make(TestSchema.Person, { name: 'Bob' });
|
|
@@ -49,4 +39,219 @@ describe('Type', () => {
|
|
|
49
39
|
expect(Schema.is(Relation.Unknown)(rel)).toBe(true);
|
|
50
40
|
});
|
|
51
41
|
});
|
|
42
|
+
|
|
43
|
+
describe('Type.Type meta-schema', () => {
|
|
44
|
+
test('Type.Type is branded as the type entity kind', ({ expect }) => {
|
|
45
|
+
// The Type.Type entity itself is an in-memory object (KindId=Object) that
|
|
46
|
+
// *declares* a type-kind schema (SchemaKindId=Type).
|
|
47
|
+
expect(Type.isTypeKind(Type.Type)).toBe(true);
|
|
48
|
+
expect(Type.isObject(Type.Type)).toBe(false);
|
|
49
|
+
expect(Type.isRelation(Type.Type)).toBe(false);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('static object/relation types are not type-kind', ({ expect }) => {
|
|
53
|
+
expect(Type.isTypeKind(TestSchema.Person)).toBe(false);
|
|
54
|
+
expect(Type.isTypeKind(TestSchema.HasManager)).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('Type.getMeta(Type.Type) reports key/version of the meta-schema', ({ expect }) => {
|
|
58
|
+
// `Type.getMeta` returns the entity's `EntityMeta`. For the static
|
|
59
|
+
// `Type.Type` meta-schema entity the key/version reflect its registry
|
|
60
|
+
// identity. The schema-kind brand is on `[SchemaKindId]`, not in meta.
|
|
61
|
+
const meta = Type.getMeta(Type.Type);
|
|
62
|
+
expect(meta.key).toBe('org.dxos.type.schema');
|
|
63
|
+
expect(meta.version).toBe('0.1.0');
|
|
64
|
+
expect(Type.isTypeKind(Type.Type)).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('Type.getURI(Type.Type) returns the meta-schema DXN', ({ expect }) => {
|
|
68
|
+
expect(Type.getURI(Type.Type).toString()).toBe('dxn:org.dxos.type.schema:0.1.0');
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe('Type.makeObjectFromJsonSchema', () => {
|
|
73
|
+
test('creates an instance branded KindId=type', ({ expect }) => {
|
|
74
|
+
const entity = Type.makeObjectFromJsonSchema({
|
|
75
|
+
typename: 'com.example.type.test',
|
|
76
|
+
version: '0.1.0',
|
|
77
|
+
jsonSchema: JsonSchema.toJsonSchema(Schema.Struct({ field: Schema.Number })),
|
|
78
|
+
});
|
|
79
|
+
expect((entity as any)[Entity.KindId]).toBe(Entity.Kind.Type);
|
|
80
|
+
// `typename` / `version` are not direct fields on a persisted `Type.Type`;
|
|
81
|
+
// they live in `EntityMeta` (the canonical registry-provenance pair).
|
|
82
|
+
// Read them via the helpers (or `Type.getMeta`).
|
|
83
|
+
expect(Type.getTypename(entity)).toBe('com.example.type.test');
|
|
84
|
+
expect(Type.getVersion(entity)).toBe('0.1.0');
|
|
85
|
+
expect(entity.jsonSchema).toBeDefined();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('defaults version to 0.0.0 for drafts', ({ expect }) => {
|
|
89
|
+
const draft = Type.makeObjectFromJsonSchema({
|
|
90
|
+
jsonSchema: JsonSchema.toJsonSchema(Schema.Struct({ field: Schema.String })),
|
|
91
|
+
});
|
|
92
|
+
// Drafts default version to `'0.0.0'` in `EntityMeta.version`; the
|
|
93
|
+
// typename (`EntityMeta.key`) is undefined until set.
|
|
94
|
+
expect(Type.getVersion(draft)).toBe('0.0.0');
|
|
95
|
+
const meta = Type.getMeta(draft);
|
|
96
|
+
expect(meta.key).toBeUndefined();
|
|
97
|
+
expect(meta.version).toBe('0.0.0');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('assigns a stable id', ({ expect }) => {
|
|
101
|
+
const a = Type.makeObjectFromJsonSchema({ jsonSchema: JsonSchema.toJsonSchema(Schema.Struct({})) });
|
|
102
|
+
const b = Type.makeObjectFromJsonSchema({ jsonSchema: JsonSchema.toJsonSchema(Schema.Struct({})) });
|
|
103
|
+
expect(typeof a.id).toBe('string');
|
|
104
|
+
expect(a.id).not.toBe(b.id);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('result satisfies isType', ({ expect }) => {
|
|
108
|
+
const entity = Type.makeObjectFromJsonSchema({
|
|
109
|
+
jsonSchema: JsonSchema.toJsonSchema(Schema.Struct({ field: Schema.Number })),
|
|
110
|
+
});
|
|
111
|
+
expect(Type.isType(entity)).toBe(true);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('Type.makeRelationFromJsonSchema', () => {
|
|
116
|
+
test('embeds source/target DXNs into jsonSchema', ({ expect }) => {
|
|
117
|
+
const entity = Type.makeRelationFromJsonSchema({
|
|
118
|
+
typename: 'com.example.type.testRel',
|
|
119
|
+
version: '0.1.0',
|
|
120
|
+
jsonSchema: JsonSchema.toJsonSchema(Schema.Struct({ note: Schema.String })),
|
|
121
|
+
source: TestSchema.Person,
|
|
122
|
+
target: TestSchema.Organization,
|
|
123
|
+
});
|
|
124
|
+
expect((entity as any)[Entity.KindId]).toBe(Entity.Kind.Type);
|
|
125
|
+
expect(entity.jsonSchema.entityKind).toBe(Entity.Kind.Relation);
|
|
126
|
+
expect((entity.jsonSchema as any).relationSource?.$ref).toBe(Type.getURI(TestSchema.Person).toString());
|
|
127
|
+
expect((entity.jsonSchema as any).relationTarget?.$ref).toBe(Type.getURI(TestSchema.Organization).toString());
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test('accepts Obj.Unknown as source/target', ({ expect }) => {
|
|
131
|
+
const entity = Type.makeRelationFromJsonSchema({
|
|
132
|
+
jsonSchema: JsonSchema.toJsonSchema(Schema.Struct({})),
|
|
133
|
+
source: Obj.Unknown,
|
|
134
|
+
target: Obj.Unknown,
|
|
135
|
+
});
|
|
136
|
+
const unknownURI = 'dxn:org.dxos.schema.anyObject:0.0.0';
|
|
137
|
+
expect((entity.jsonSchema as any).relationSource?.$ref).toBe(unknownURI);
|
|
138
|
+
expect((entity.jsonSchema as any).relationTarget?.$ref).toBe(unknownURI);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
test('defaults version to 0.0.0 for drafts', ({ expect }) => {
|
|
142
|
+
const draft = Type.makeRelationFromJsonSchema({
|
|
143
|
+
jsonSchema: JsonSchema.toJsonSchema(Schema.Struct({})),
|
|
144
|
+
source: TestSchema.Person,
|
|
145
|
+
target: TestSchema.Person,
|
|
146
|
+
});
|
|
147
|
+
expect(Type.getVersion(draft)).toBe('0.0.0');
|
|
148
|
+
const meta = Type.getMeta(draft);
|
|
149
|
+
expect(meta.key).toBeUndefined();
|
|
150
|
+
expect(meta.version).toBe('0.0.0');
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
describe('Obj/Relation/Entity.getType', () => {
|
|
155
|
+
test('Obj.getType returns the static type entity for instances of Type.makeObject', ({ expect }) => {
|
|
156
|
+
const person = Obj.make(TestSchema.Person, { name: 'Alice' });
|
|
157
|
+
expect(Obj.getType(person)).toBe(TestSchema.Person);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test('Relation.getType returns the static type entity for instances of Type.makeRelation', ({ expect }) => {
|
|
161
|
+
const a = Obj.make(TestSchema.Person, { name: 'A' });
|
|
162
|
+
const b = Obj.make(TestSchema.Person, { name: 'B' });
|
|
163
|
+
const rel = Relation.make(TestSchema.HasManager, {
|
|
164
|
+
[Relation.Source]: a,
|
|
165
|
+
[Relation.Target]: b,
|
|
166
|
+
});
|
|
167
|
+
expect(Relation.getType(rel)).toBe(TestSchema.HasManager);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test('Entity.getType narrows uniformly across object/relation instances', ({ expect }) => {
|
|
171
|
+
const person = Obj.make(TestSchema.Person, { name: 'A' });
|
|
172
|
+
const a = Obj.make(TestSchema.Person, { name: 'A' });
|
|
173
|
+
const b = Obj.make(TestSchema.Person, { name: 'B' });
|
|
174
|
+
const rel = Relation.make(TestSchema.HasManager, {
|
|
175
|
+
[Relation.Source]: a,
|
|
176
|
+
[Relation.Target]: b,
|
|
177
|
+
});
|
|
178
|
+
expect(Entity.getType(person)).toBe(TestSchema.Person);
|
|
179
|
+
expect(Entity.getType(rel)).toBe(TestSchema.HasManager);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
describe('static type factories', () => {
|
|
184
|
+
test('Type.makeObject stamps schema-kind=object', ({ expect }) => {
|
|
185
|
+
expect((TestSchema.Person as any)['~@dxos/echo/SchemaKind']).toBe(Entity.Kind.Object);
|
|
186
|
+
expect(Type.isObject(TestSchema.Person)).toBe(true);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
test('Type.makeRelation stamps schema-kind=relation', ({ expect }) => {
|
|
190
|
+
expect((TestSchema.HasManager as any)['~@dxos/echo/SchemaKind']).toBe(Entity.Kind.Relation);
|
|
191
|
+
expect(Type.isRelation(TestSchema.HasManager)).toBe(true);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
test('Type.getURI returns the DXN for static types', ({ expect }) => {
|
|
195
|
+
expect(Type.getURI(TestSchema.Person).toString()).toBe('dxn:com.example.type.person:0.1.0');
|
|
196
|
+
expect(Type.getURI(TestSchema.HasManager).toString()).toBe('dxn:com.example.type.hasManager:0.1.0');
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
describe('deterministic id default', () => {
|
|
201
|
+
// The default id is `EntityId.deterministic(typename, version)` — required so that
|
|
202
|
+
// `Type.makeObject(...)` never calls `crypto.getRandomValues()` at module-evaluation
|
|
203
|
+
// time (forbidden by Cloudflare workerd in global scope).
|
|
204
|
+
const personDxn = DXN.make('com.example.type.deterministic.person', '0.1.0');
|
|
205
|
+
const worksForDxn = DXN.make('com.example.type.deterministic.worksFor', '0.1.0');
|
|
206
|
+
|
|
207
|
+
test('Type.makeObject with the same DXN twice yields entities with identical ids', ({ expect }) => {
|
|
208
|
+
const a = Schema.Struct({ name: Schema.String }).pipe(Type.makeObject(personDxn));
|
|
209
|
+
const b = Schema.Struct({ name: Schema.String }).pipe(Type.makeObject(personDxn));
|
|
210
|
+
expect(a.id).toBe(b.id);
|
|
211
|
+
expect(a.id).toBe(EntityId.deterministic('com.example.type.deterministic.person', '0.1.0'));
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test('different versions produce different ids', ({ expect }) => {
|
|
215
|
+
const v1 = Schema.Struct({ name: Schema.String }).pipe(
|
|
216
|
+
Type.makeObject(DXN.make('com.example.type.deterministic.person', '0.1.0')),
|
|
217
|
+
);
|
|
218
|
+
const v2 = Schema.Struct({ name: Schema.String }).pipe(
|
|
219
|
+
Type.makeObject(DXN.make('com.example.type.deterministic.person', '0.2.0')),
|
|
220
|
+
);
|
|
221
|
+
expect(v1.id).not.toBe(v2.id);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test('Type.makeObject({ id }) override is honoured', ({ expect }) => {
|
|
225
|
+
const explicit = EntityId.random();
|
|
226
|
+
const entity = Schema.Struct({ name: Schema.String }).pipe(Type.makeObject(personDxn, { id: explicit }));
|
|
227
|
+
expect(entity.id).toBe(explicit);
|
|
228
|
+
// And the default still kicks in when no override is supplied.
|
|
229
|
+
const defaultEntity = Schema.Struct({ name: Schema.String }).pipe(Type.makeObject(personDxn));
|
|
230
|
+
expect(defaultEntity.id).not.toBe(explicit);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
test('Type.makeRelation defaults id to deterministic(typename, version)', ({ expect }) => {
|
|
234
|
+
const a = Schema.Struct({ since: Schema.Number }).pipe(
|
|
235
|
+
Type.makeRelation({ dxn: worksForDxn, source: TestSchema.Person, target: TestSchema.Organization }),
|
|
236
|
+
);
|
|
237
|
+
const b = Schema.Struct({ since: Schema.Number }).pipe(
|
|
238
|
+
Type.makeRelation({ dxn: worksForDxn, source: TestSchema.Person, target: TestSchema.Organization }),
|
|
239
|
+
);
|
|
240
|
+
expect(a.id).toBe(b.id);
|
|
241
|
+
expect(a.id).toBe(EntityId.deterministic('com.example.type.deterministic.worksFor', '0.1.0'));
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
test('Type.makeRelation({ id }) override is honoured', ({ expect }) => {
|
|
245
|
+
const explicit = EntityId.random();
|
|
246
|
+
const entity = Schema.Struct({ since: Schema.Number }).pipe(
|
|
247
|
+
Type.makeRelation({
|
|
248
|
+
dxn: worksForDxn,
|
|
249
|
+
source: TestSchema.Person,
|
|
250
|
+
target: TestSchema.Organization,
|
|
251
|
+
id: explicit,
|
|
252
|
+
}),
|
|
253
|
+
);
|
|
254
|
+
expect(entity.id).toBe(explicit);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
52
257
|
});
|