@dxos/echo 0.9.0 → 0.9.1-staging.ee54ba693a
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/dist/lib/neutral/Annotation.mjs +30 -8
- package/dist/lib/neutral/Database.mjs +7 -3
- package/dist/lib/neutral/Entity.mjs +15 -11
- package/dist/lib/neutral/Err.mjs +7 -3
- package/dist/lib/neutral/Feed.mjs +15 -19
- package/dist/lib/neutral/Filter.mjs +13 -11
- package/dist/lib/neutral/Format.mjs +3 -7
- package/dist/lib/neutral/JsonSchema.mjs +7 -7
- package/dist/lib/neutral/Migration.mjs +11 -11
- package/dist/lib/neutral/Obj.mjs +19 -13
- package/dist/lib/neutral/Order.mjs +1 -1
- package/dist/lib/neutral/Query.mjs +17 -17
- package/dist/lib/neutral/QueryResult.mjs +1 -1
- package/dist/lib/neutral/Ref.mjs +6 -6
- package/dist/lib/neutral/Registry.mjs +1 -1
- package/dist/lib/neutral/Relation.mjs +12 -12
- package/dist/lib/neutral/Tag.mjs +15 -15
- package/dist/lib/neutral/Text.mjs +25 -0
- package/dist/lib/neutral/Text.mjs.map +7 -0
- package/dist/lib/neutral/Type.mjs +10 -10
- package/dist/lib/neutral/chunk-2HKGAQM4.mjs +1394 -0
- package/dist/lib/neutral/chunk-2HKGAQM4.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-O6BH7EPN.mjs → chunk-2ZHECXUR.mjs} +5 -4
- package/dist/lib/neutral/chunk-2ZHECXUR.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-QQIYS74I.mjs → chunk-3KTE2Y7Q.mjs} +20 -20
- package/dist/lib/neutral/chunk-3KTE2Y7Q.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-R5W6DXR4.mjs → chunk-3TN2VMI4.mjs} +72 -36
- package/dist/lib/neutral/chunk-3TN2VMI4.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-5SMDBFVB.mjs → chunk-42L4HJ3Z.mjs} +11 -15
- package/dist/lib/neutral/chunk-42L4HJ3Z.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-7PI7C4EF.mjs → chunk-4A2NWKRJ.mjs} +5 -5
- package/dist/lib/neutral/chunk-ACFAOTKJ.mjs +1531 -0
- package/dist/lib/neutral/chunk-ACFAOTKJ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-SBVFRTST.mjs → chunk-BEFR7LEA.mjs} +20 -10
- package/dist/lib/neutral/chunk-BEFR7LEA.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-6M2Z6WBH.mjs → chunk-BXIKXT7Q.mjs} +2 -6
- package/dist/lib/neutral/{chunk-6M2Z6WBH.mjs.map → chunk-BXIKXT7Q.mjs.map} +1 -1
- package/dist/lib/neutral/{chunk-UUP46KUQ.mjs → chunk-C57XMMBY.mjs} +21 -20
- package/dist/lib/neutral/chunk-C57XMMBY.mjs.map +7 -0
- package/dist/lib/neutral/chunk-C62JYFAD.mjs +183 -0
- package/dist/lib/neutral/chunk-C62JYFAD.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-MZ7K3MLL.mjs → chunk-FSGX2R62.mjs} +3 -3
- package/dist/lib/neutral/chunk-FSGX2R62.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-TYGKCRMK.mjs → chunk-HBXT3GSB.mjs} +37 -15
- package/dist/lib/neutral/chunk-HBXT3GSB.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-WU3GIANS.mjs → chunk-IQR45HAD.mjs} +1 -1
- package/dist/lib/neutral/chunk-IQR45HAD.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-TFEWTY5A.mjs → chunk-KCBW4BR6.mjs} +4 -8
- package/dist/lib/neutral/chunk-KCBW4BR6.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-WTQJHC75.mjs → chunk-L3E5IXAE.mjs} +225 -45
- package/dist/lib/neutral/chunk-L3E5IXAE.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-EVK6XBXO.mjs → chunk-PRC4FEKJ.mjs} +2 -2
- package/dist/lib/neutral/chunk-PRC4FEKJ.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-6YDI3J37.mjs → chunk-SCT6FFCR.mjs} +9 -4
- package/dist/lib/neutral/chunk-SCT6FFCR.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-BBFJWWAV.mjs → chunk-TOCVVFK2.mjs} +26 -2
- package/dist/lib/neutral/chunk-TOCVVFK2.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-RIVWNMSF.mjs → chunk-U53LSQQA.mjs} +3 -3
- package/dist/lib/neutral/{chunk-RIVWNMSF.mjs.map → chunk-U53LSQQA.mjs.map} +1 -1
- package/dist/lib/neutral/{chunk-IGK6FN65.mjs → chunk-UGFFV2FR.mjs} +2 -2
- package/dist/lib/neutral/{chunk-35INCYOE.mjs → chunk-UWLP4RFM.mjs} +1 -1
- package/dist/lib/neutral/chunk-UWLP4RFM.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-LWXVKPPW.mjs → chunk-UZHCQ6NI.mjs} +13 -11
- package/dist/lib/neutral/{chunk-LWXVKPPW.mjs.map → chunk-UZHCQ6NI.mjs.map} +3 -3
- package/dist/lib/neutral/{chunk-5SUJPHAE.mjs → chunk-WKIT2YY5.mjs} +2 -2
- package/dist/lib/neutral/{chunk-T6E37YIP.mjs → chunk-XB6ISRAO.mjs} +38 -18
- package/dist/lib/neutral/chunk-XB6ISRAO.mjs.map +7 -0
- package/dist/lib/neutral/chunk-XXL42WCB.mjs +84 -0
- package/dist/lib/neutral/chunk-XXL42WCB.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-ZGNNFYHS.mjs → chunk-XXWK4J53.mjs} +27 -42
- package/dist/lib/neutral/chunk-XXWK4J53.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +30 -26
- package/dist/lib/neutral/internal/index.mjs +111 -69
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/testing/index.mjs +79 -60
- package/dist/lib/neutral/testing/index.mjs.map +3 -3
- package/dist/types/src/Annotation.d.ts +35 -1
- package/dist/types/src/Annotation.d.ts.map +1 -1
- package/dist/types/src/Collection.d.ts +9 -8
- package/dist/types/src/Collection.d.ts.map +1 -1
- package/dist/types/src/Database.d.ts +38 -0
- package/dist/types/src/Database.d.ts.map +1 -1
- package/dist/types/src/Dataset.d.ts +1 -16
- package/dist/types/src/Dataset.d.ts.map +1 -1
- package/dist/types/src/Entity.d.ts +2 -0
- package/dist/types/src/Entity.d.ts.map +1 -1
- package/dist/types/src/Err.d.ts +67 -0
- package/dist/types/src/Err.d.ts.map +1 -1
- package/dist/types/src/Feed.d.ts +59 -80
- package/dist/types/src/Feed.d.ts.map +1 -1
- package/dist/types/src/Filter.d.ts +9 -1
- package/dist/types/src/Filter.d.ts.map +1 -1
- package/dist/types/src/Hypergraph.d.ts +2 -9
- package/dist/types/src/Hypergraph.d.ts.map +1 -1
- package/dist/types/src/Migration.d.ts +1 -1
- package/dist/types/src/Migration.d.ts.map +1 -1
- package/dist/types/src/Obj.d.ts +33 -6
- package/dist/types/src/Obj.d.ts.map +1 -1
- package/dist/types/src/Order.d.ts +1 -1
- package/dist/types/src/Order.d.ts.map +1 -1
- package/dist/types/src/Query.d.ts +1 -1
- package/dist/types/src/Query.d.ts.map +1 -1
- package/dist/types/src/QueryResult.d.ts +2 -2
- package/dist/types/src/QueryResult.d.ts.map +1 -1
- package/dist/types/src/Ref.d.ts +10 -6
- package/dist/types/src/Ref.d.ts.map +1 -1
- package/dist/types/src/Registry.d.ts +1 -1
- package/dist/types/src/Relation.d.ts.map +1 -1
- package/dist/types/src/Tag.d.ts +11 -13
- package/dist/types/src/Tag.d.ts.map +1 -1
- package/dist/types/src/Text.d.ts +41 -0
- package/dist/types/src/Text.d.ts.map +1 -0
- package/dist/types/src/Text.test.d.ts +2 -0
- package/dist/types/src/Text.test.d.ts.map +1 -0
- package/dist/types/src/Type.d.ts +38 -21
- package/dist/types/src/Type.d.ts.map +1 -1
- package/dist/types/src/View.d.ts +8 -9
- package/dist/types/src/View.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/annotations.d.ts +50 -0
- package/dist/types/src/internal/Annotation/annotations.d.ts.map +1 -1
- package/dist/types/src/internal/Annotation/atoms.d.ts +14 -0
- package/dist/types/src/internal/Annotation/atoms.d.ts.map +1 -0
- package/dist/types/src/internal/Annotation/entity-dictionary.d.ts +13 -0
- package/dist/types/src/internal/Annotation/entity-dictionary.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/api.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/guard.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/model.d.ts +1 -1
- package/dist/types/src/internal/Entity/model.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/object.d.ts +5 -1
- package/dist/types/src/internal/Entity/object.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/relation.d.ts +7 -0
- package/dist/types/src/internal/Entity/relation.d.ts.map +1 -1
- package/dist/types/src/internal/Entity/type-uri.d.ts.map +1 -1
- package/dist/types/src/internal/Filter/index.d.ts +2 -0
- package/dist/types/src/internal/Filter/index.d.ts.map +1 -0
- package/dist/types/src/internal/Filter/match.d.ts +22 -0
- package/dist/types/src/internal/Filter/match.d.ts.map +1 -0
- package/dist/types/src/internal/Format/format.d.ts +0 -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/string.d.ts +0 -8
- package/dist/types/src/internal/Format/string.d.ts.map +1 -1
- package/dist/types/src/internal/Format/types.d.ts +2 -1
- package/dist/types/src/internal/Format/types.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/atoms.d.ts +12 -3
- package/dist/types/src/internal/Obj/atoms.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/clone.d.ts +2 -1
- package/dist/types/src/internal/Obj/clone.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/create-object.d.ts +3 -4
- package/dist/types/src/internal/Obj/create-object.d.ts.map +1 -1
- package/dist/types/src/internal/Obj/json-serializer.d.ts.map +1 -1
- package/dist/types/src/internal/Query/index.d.ts +1 -0
- package/dist/types/src/internal/Query/index.d.ts.map +1 -1
- package/dist/types/src/internal/Query/query-result-effect.d.ts +9 -0
- package/dist/types/src/internal/Query/query-result-effect.d.ts.map +1 -0
- package/dist/types/src/internal/Ref/atoms.d.ts +1 -2
- package/dist/types/src/internal/Ref/atoms.d.ts.map +1 -1
- package/dist/types/src/internal/Ref/index.d.ts +1 -0
- package/dist/types/src/internal/Ref/index.d.ts.map +1 -1
- package/dist/types/src/internal/Ref/ref.d.ts +79 -8
- package/dist/types/src/internal/Ref/ref.d.ts.map +1 -1
- package/dist/types/src/internal/Ref/strong-deps.d.ts +35 -0
- package/dist/types/src/internal/Ref/strong-deps.d.ts.map +1 -0
- package/dist/types/src/internal/common/atom-snapshot.d.ts +8 -0
- package/dist/types/src/internal/common/atom-snapshot.d.ts.map +1 -0
- package/dist/types/src/internal/common/proxy/make-object.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/proxy-types.d.ts +12 -0
- package/dist/types/src/internal/common/proxy/proxy-types.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/proxy-utils.d.ts +25 -0
- package/dist/types/src/internal/common/proxy/proxy-utils.d.ts.map +1 -1
- package/dist/types/src/internal/common/proxy/schema-validator.d.ts +5 -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 +17 -0
- package/dist/types/src/internal/common/proxy/typed-handler.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/entity.d.ts +4 -4
- package/dist/types/src/internal/common/types/entity.d.ts.map +1 -1
- package/dist/types/src/internal/common/types/meta.d.ts +2 -4
- package/dist/types/src/internal/common/types/meta.d.ts.map +1 -1
- 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 +42 -171
- package/dist/types/src/testing/test-schema.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +20 -13
- package/src/Annotation.test.ts +257 -10
- package/src/Annotation.ts +58 -4
- package/src/Collection.ts +10 -12
- package/src/Database.ts +55 -21
- package/src/Entity.ts +3 -1
- package/src/Err.ts +22 -0
- package/src/Feed.ts +117 -141
- package/src/Filter.test.ts +38 -0
- package/src/Filter.ts +17 -3
- package/src/Hypergraph.ts +2 -11
- package/src/Migration.ts +1 -1
- package/src/Obj.test.ts +92 -12
- package/src/Obj.ts +38 -5
- package/src/Order.ts +3 -3
- package/src/Query.test.ts +2 -2
- package/src/Query.ts +16 -16
- package/src/QueryResult.ts +2 -2
- package/src/Ref.ts +14 -6
- package/src/Registry.ts +1 -1
- package/src/Relation.ts +1 -1
- package/src/Tag.ts +13 -16
- package/src/Text.test.ts +186 -0
- package/src/Text.ts +116 -0
- package/src/Type.test.ts +52 -24
- package/src/Type.ts +85 -33
- package/src/View.ts +22 -30
- package/src/index.ts +1 -1
- package/src/internal/Annotation/annotations.ts +71 -2
- package/src/internal/Annotation/atoms.ts +107 -0
- package/src/internal/Annotation/entity-dictionary.ts +40 -37
- package/src/internal/Entity/api.ts +1 -1
- package/src/internal/Entity/guard.ts +2 -1
- package/src/internal/Entity/model.ts +2 -2
- package/src/internal/Entity/object.ts +14 -1
- package/src/internal/Entity/relation.ts +19 -0
- package/src/internal/Entity/type-uri.ts +3 -1
- package/src/internal/Filter/index.ts +5 -0
- package/src/internal/Filter/match.ts +284 -0
- package/src/internal/Format/format.ts +0 -2
- package/src/internal/Format/index.ts +2 -2
- package/src/internal/Format/string.ts +0 -12
- package/src/internal/Format/types.ts +4 -2
- package/src/internal/JsonSchema/json-schema.test.ts +82 -54
- package/src/internal/Obj/atoms.ts +62 -18
- package/src/internal/Obj/clone.ts +61 -20
- package/src/internal/Obj/create-object.test.ts +3 -3
- package/src/internal/Obj/create-object.ts +3 -4
- package/src/internal/Obj/inspect.ts +1 -1
- package/src/internal/Obj/json-serializer.test.ts +7 -5
- package/src/internal/Obj/json-serializer.ts +4 -4
- package/src/internal/Obj/schema-validator.test.ts +53 -0
- package/src/internal/Obj/set-value.test.ts +29 -19
- package/src/internal/Query/index.ts +1 -0
- package/src/internal/Query/query-result-effect.ts +35 -0
- package/src/internal/Ref/atoms.ts +23 -3
- package/src/internal/Ref/index.ts +1 -0
- package/src/internal/Ref/ref.test.ts +8 -8
- package/src/internal/Ref/ref.ts +122 -39
- package/src/internal/Ref/strong-deps.ts +107 -0
- package/src/internal/common/atom-snapshot.ts +19 -0
- package/src/internal/common/proxy/make-object.ts +1 -1
- package/src/internal/common/proxy/proxy-types.ts +20 -0
- package/src/internal/common/proxy/proxy-utils.ts +37 -1
- package/src/internal/common/proxy/reactive-array.ts +3 -3
- package/src/internal/common/proxy/reactive.test.ts +1 -1
- package/src/internal/common/proxy/schema-validator.ts +181 -8
- package/src/internal/common/proxy/typed-handler.ts +254 -76
- package/src/internal/common/types/entity.ts +15 -7
- package/src/internal/index.ts +1 -0
- package/src/testing/test-schema.ts +75 -90
- package/dist/lib/neutral/chunk-35INCYOE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-3PBP4V4O.mjs +0 -101
- package/dist/lib/neutral/chunk-3PBP4V4O.mjs.map +0 -7
- package/dist/lib/neutral/chunk-4ZUHOTCG.mjs +0 -184
- package/dist/lib/neutral/chunk-4ZUHOTCG.mjs.map +0 -7
- package/dist/lib/neutral/chunk-5SMDBFVB.mjs.map +0 -7
- package/dist/lib/neutral/chunk-6YDI3J37.mjs.map +0 -7
- package/dist/lib/neutral/chunk-7FPIAJIV.mjs +0 -2279
- package/dist/lib/neutral/chunk-7FPIAJIV.mjs.map +0 -7
- package/dist/lib/neutral/chunk-BBFJWWAV.mjs.map +0 -7
- package/dist/lib/neutral/chunk-EVK6XBXO.mjs.map +0 -7
- package/dist/lib/neutral/chunk-MZ7K3MLL.mjs.map +0 -7
- package/dist/lib/neutral/chunk-O6BH7EPN.mjs.map +0 -7
- package/dist/lib/neutral/chunk-QQIYS74I.mjs.map +0 -7
- package/dist/lib/neutral/chunk-R5W6DXR4.mjs.map +0 -7
- package/dist/lib/neutral/chunk-SBVFRTST.mjs.map +0 -7
- package/dist/lib/neutral/chunk-T6E37YIP.mjs.map +0 -7
- package/dist/lib/neutral/chunk-TFEWTY5A.mjs.map +0 -7
- package/dist/lib/neutral/chunk-TYGKCRMK.mjs.map +0 -7
- package/dist/lib/neutral/chunk-UUP46KUQ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-WTQJHC75.mjs.map +0 -7
- package/dist/lib/neutral/chunk-WU3GIANS.mjs.map +0 -7
- package/dist/lib/neutral/chunk-ZGNNFYHS.mjs.map +0 -7
- package/dist/types/src/exemplars.test.d.ts +0 -2
- package/dist/types/src/exemplars.test.d.ts.map +0 -1
- package/dist/types/src/hierarchy.test.d.ts +0 -2
- package/dist/types/src/hierarchy.test.d.ts.map +0 -1
- package/src/exemplars.test.ts +0 -21
- package/src/hierarchy.test.ts +0 -33
- /package/dist/lib/neutral/{chunk-7PI7C4EF.mjs.map → chunk-4A2NWKRJ.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-IGK6FN65.mjs.map → chunk-UGFFV2FR.mjs.map} +0 -0
- /package/dist/lib/neutral/{chunk-5SUJPHAE.mjs.map → chunk-WKIT2YY5.mjs.map} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/echo",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.1-staging.ee54ba693a",
|
|
4
4
|
"description": "ECHO API",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -123,6 +123,11 @@
|
|
|
123
123
|
"types": "./dist/types/src/Tag.d.ts",
|
|
124
124
|
"default": "./dist/lib/neutral/Tag.mjs"
|
|
125
125
|
},
|
|
126
|
+
"./Text": {
|
|
127
|
+
"source": "./src/Text.ts",
|
|
128
|
+
"types": "./dist/types/src/Text.d.ts",
|
|
129
|
+
"default": "./dist/lib/neutral/Text.mjs"
|
|
130
|
+
},
|
|
126
131
|
"./Type": {
|
|
127
132
|
"source": "./src/Type.ts",
|
|
128
133
|
"types": "./dist/types/src/Type.d.ts",
|
|
@@ -135,20 +140,22 @@
|
|
|
135
140
|
],
|
|
136
141
|
"dependencies": {
|
|
137
142
|
"@effect-atom/atom": "^0.5.3",
|
|
138
|
-
"effect": "3.21.
|
|
139
|
-
"
|
|
140
|
-
"@dxos/async": "0.9.
|
|
141
|
-
"@dxos/
|
|
142
|
-
"@dxos/
|
|
143
|
-
"@dxos/
|
|
144
|
-
"@dxos/
|
|
145
|
-
"@dxos/
|
|
146
|
-
"@dxos/
|
|
147
|
-
"@dxos/log": "0.9.
|
|
148
|
-
"@dxos/
|
|
143
|
+
"effect": "3.21.4",
|
|
144
|
+
"semver": "^7.7.4",
|
|
145
|
+
"@dxos/async": "0.9.1-staging.ee54ba693a",
|
|
146
|
+
"@dxos/debug": "0.9.1-staging.ee54ba693a",
|
|
147
|
+
"@dxos/echo-protocol": "0.9.1-staging.ee54ba693a",
|
|
148
|
+
"@dxos/effect": "0.9.1-staging.ee54ba693a",
|
|
149
|
+
"@dxos/errors": "0.9.1-staging.ee54ba693a",
|
|
150
|
+
"@dxos/invariant": "0.9.1-staging.ee54ba693a",
|
|
151
|
+
"@dxos/keys": "0.9.1-staging.ee54ba693a",
|
|
152
|
+
"@dxos/log": "0.9.1-staging.ee54ba693a",
|
|
153
|
+
"@dxos/node-std": "0.9.1-staging.ee54ba693a",
|
|
154
|
+
"@dxos/util": "0.9.1-staging.ee54ba693a"
|
|
149
155
|
},
|
|
150
156
|
"devDependencies": {
|
|
151
|
-
"@types/node": "22.10.2"
|
|
157
|
+
"@types/node": "22.10.2",
|
|
158
|
+
"@types/semver": "^7.7.1"
|
|
152
159
|
},
|
|
153
160
|
"publishConfig": {
|
|
154
161
|
"access": "public"
|
package/src/Annotation.test.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Copyright 2026 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import * as Registry from '@effect-atom/atom/Registry';
|
|
5
6
|
import * as Option from 'effect/Option';
|
|
6
7
|
import * as Schema from 'effect/Schema';
|
|
7
8
|
import * as SchemaAST from 'effect/SchemaAST';
|
|
@@ -11,6 +12,7 @@ import { DXN } from '@dxos/keys';
|
|
|
11
12
|
|
|
12
13
|
import * as Annotation from './Annotation';
|
|
13
14
|
import * as Obj from './Obj';
|
|
15
|
+
import * as Ref from './Ref';
|
|
14
16
|
import * as Type from './Type';
|
|
15
17
|
|
|
16
18
|
describe('Annotation', () => {
|
|
@@ -347,11 +349,11 @@ describe('Annotation', () => {
|
|
|
347
349
|
schema: Schema.String,
|
|
348
350
|
});
|
|
349
351
|
|
|
350
|
-
const TaggedPerson =
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
.pipe(ColorAnnotation.set('teal'))
|
|
354
|
-
|
|
352
|
+
const TaggedPerson = Type.makeObject(DXN.make('com.example.type.taggedperson', '0.1.0'))(
|
|
353
|
+
Schema.Struct({
|
|
354
|
+
name: Schema.String,
|
|
355
|
+
}).pipe(ColorAnnotation.set('teal')),
|
|
356
|
+
);
|
|
355
357
|
|
|
356
358
|
const schema = Type.getSchema(TaggedPerson);
|
|
357
359
|
const result = ColorAnnotation.get(schema);
|
|
@@ -366,11 +368,11 @@ describe('Annotation', () => {
|
|
|
366
368
|
id: 'org.dxos.annotation.color',
|
|
367
369
|
schema: Schema.String,
|
|
368
370
|
});
|
|
369
|
-
const Person =
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
.pipe(ColorAnnotation.set('schema-teal'))
|
|
373
|
-
|
|
371
|
+
const Person = Type.makeObject(DXN.make('com.example.type.taggedperson', '0.1.0'))(
|
|
372
|
+
Schema.Struct({
|
|
373
|
+
name: Schema.String,
|
|
374
|
+
}).pipe(ColorAnnotation.set('schema-teal')),
|
|
375
|
+
);
|
|
374
376
|
|
|
375
377
|
test('set and get on Obj.make instance', ({ expect }) => {
|
|
376
378
|
const person = Obj.make(Person, { name: 'Alice' });
|
|
@@ -436,4 +438,249 @@ describe('Annotation', () => {
|
|
|
436
438
|
expect(Option.getOrThrow(Annotation.get(snapshot, ColorAnnotation))).toBe('snapshot-color');
|
|
437
439
|
});
|
|
438
440
|
});
|
|
441
|
+
|
|
442
|
+
describe('atom', () => {
|
|
443
|
+
// Record-valued annotation mirroring a per-key ordering (e.g. SectionOrderAnnotation).
|
|
444
|
+
const OrderAnnotation = Annotation.make({
|
|
445
|
+
id: 'org.dxos.test.order',
|
|
446
|
+
schema: Schema.Record({ key: Schema.String, value: Schema.Array(Schema.String) }),
|
|
447
|
+
});
|
|
448
|
+
const Container = Type.makeObject(DXN.make('com.example.type.container', '0.1.0'))(
|
|
449
|
+
Schema.Struct({ name: Schema.String }),
|
|
450
|
+
);
|
|
451
|
+
|
|
452
|
+
const setOrder = (obj: Obj.Unknown, order: Record<string, string[]>) =>
|
|
453
|
+
Obj.update(obj, (obj) => {
|
|
454
|
+
Annotation.set(obj, OrderAnnotation, order);
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
test('atomProperty reads the typed slice for a key', ({ expect }) => {
|
|
458
|
+
const registry = Registry.make();
|
|
459
|
+
const obj = Obj.make(Container, { name: 'A' });
|
|
460
|
+
setOrder(obj, { typeA: ['x', 'y'], typeB: ['m'] });
|
|
461
|
+
|
|
462
|
+
const atomA = Annotation.atomProperty(obj, OrderAnnotation, 'typeA');
|
|
463
|
+
expect(registry.get(atomA)).toEqual(['x', 'y']);
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
test('atomProperty returns undefined for a missing key or annotation', ({ expect }) => {
|
|
467
|
+
const registry = Registry.make();
|
|
468
|
+
const obj = Obj.make(Container, { name: 'A' });
|
|
469
|
+
|
|
470
|
+
const missingAnnotation = Annotation.atomProperty(obj, OrderAnnotation, 'typeA');
|
|
471
|
+
expect(registry.get(missingAnnotation)).toBeUndefined();
|
|
472
|
+
|
|
473
|
+
setOrder(obj, { typeA: ['x'] });
|
|
474
|
+
const missingKey = Annotation.atomProperty(obj, OrderAnnotation, 'typeZ');
|
|
475
|
+
expect(registry.get(missingKey)).toBeUndefined();
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
test('atomProperty updates when its own key changes', ({ expect }) => {
|
|
479
|
+
const registry = Registry.make();
|
|
480
|
+
const obj = Obj.make(Container, { name: 'A' });
|
|
481
|
+
setOrder(obj, { typeA: ['x', 'y'] });
|
|
482
|
+
|
|
483
|
+
const atomA = Annotation.atomProperty(obj, OrderAnnotation, 'typeA');
|
|
484
|
+
let fires = 0;
|
|
485
|
+
registry.subscribe(atomA, () => {
|
|
486
|
+
fires++;
|
|
487
|
+
});
|
|
488
|
+
expect(registry.get(atomA)).toEqual(['x', 'y']);
|
|
489
|
+
|
|
490
|
+
setOrder(obj, { typeA: ['y', 'x'] });
|
|
491
|
+
expect(registry.get(atomA)).toEqual(['y', 'x']);
|
|
492
|
+
expect(fires).toBeGreaterThan(0);
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
test('atomProperty reflects only its own key', ({ expect }) => {
|
|
496
|
+
const registry = Registry.make();
|
|
497
|
+
const obj = Obj.make(Container, { name: 'A' });
|
|
498
|
+
setOrder(obj, { typeA: ['x', 'y'], typeB: ['m'] });
|
|
499
|
+
|
|
500
|
+
const atomA = Annotation.atomProperty(obj, OrderAnnotation, 'typeA');
|
|
501
|
+
expect(registry.get(atomA)).toEqual(['x', 'y']);
|
|
502
|
+
|
|
503
|
+
// Changing a different key leaves typeA's value content unchanged.
|
|
504
|
+
setOrder(obj, { typeA: ['x', 'y'], typeB: ['m', 'n'] });
|
|
505
|
+
expect(registry.get(atomA)).toEqual(['x', 'y']);
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
test('atom exposes the whole annotation value as an Option', ({ expect }) => {
|
|
509
|
+
const registry = Registry.make();
|
|
510
|
+
const obj = Obj.make(Container, { name: 'A' });
|
|
511
|
+
|
|
512
|
+
const wholeAtom = Annotation.atom(obj, OrderAnnotation);
|
|
513
|
+
expect(Option.isNone(registry.get(wholeAtom))).toBe(true);
|
|
514
|
+
|
|
515
|
+
setOrder(obj, { typeA: ['x'] });
|
|
516
|
+
expect(Option.getOrThrow(registry.get(wholeAtom))).toEqual({ typeA: ['x'] });
|
|
517
|
+
});
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
describe('reactive in-place mutation', () => {
|
|
521
|
+
const OrderAnnotation = Annotation.make({
|
|
522
|
+
id: 'org.dxos.test.mutable-order',
|
|
523
|
+
schema: Schema.Record({ key: Schema.String, value: Schema.Array(Schema.String) }),
|
|
524
|
+
});
|
|
525
|
+
const RefOrderAnnotation = Annotation.make({
|
|
526
|
+
id: 'org.dxos.test.mutable-ref-order',
|
|
527
|
+
schema: Schema.Record({ key: Schema.String, value: Schema.Array(Ref.Ref(Obj.Unknown)) }),
|
|
528
|
+
});
|
|
529
|
+
const Item = Type.makeObject(DXN.make('com.example.type.mutableItem', '0.1.0'))(
|
|
530
|
+
Schema.Struct({ name: Schema.String }),
|
|
531
|
+
);
|
|
532
|
+
const Container = Type.makeObject(DXN.make('com.example.type.mutableContainer', '0.1.0'))(
|
|
533
|
+
Schema.Struct({ name: Schema.String }),
|
|
534
|
+
);
|
|
535
|
+
|
|
536
|
+
test('push to an annotation array in place without Annotation.set', ({ expect }) => {
|
|
537
|
+
const registry = Registry.make();
|
|
538
|
+
const obj = Obj.make(Container, { name: 'A' });
|
|
539
|
+
Obj.update(obj, (obj) => Annotation.set(obj, OrderAnnotation, { typeA: ['x', 'y'] }));
|
|
540
|
+
|
|
541
|
+
const atomA = Annotation.atomProperty(obj, OrderAnnotation, 'typeA');
|
|
542
|
+
expect(registry.get(atomA)).toEqual(['x', 'y']);
|
|
543
|
+
|
|
544
|
+
Annotation.update(obj, OrderAnnotation, (order) => {
|
|
545
|
+
order.typeA.push('z');
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
expect(registry.get(atomA)).toEqual(['x', 'y', 'z']);
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
test('splice an annotation array in place reorders the value', ({ expect }) => {
|
|
552
|
+
const registry = Registry.make();
|
|
553
|
+
const obj = Obj.make(Container, { name: 'A' });
|
|
554
|
+
Obj.update(obj, (obj) => Annotation.set(obj, OrderAnnotation, { typeA: ['x', 'y', 'z'] }));
|
|
555
|
+
|
|
556
|
+
const atomA = Annotation.atomProperty(obj, OrderAnnotation, 'typeA');
|
|
557
|
+
|
|
558
|
+
Annotation.update(obj, OrderAnnotation, (order) => {
|
|
559
|
+
order.typeA.splice(0, order.typeA.length, 'z', 'x', 'y');
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
expect(registry.get(atomA)).toEqual(['z', 'x', 'y']);
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
test('in-place mutation of one key leaves other keys untouched', ({ expect }) => {
|
|
566
|
+
const obj = Obj.make(Container, { name: 'A' });
|
|
567
|
+
Obj.update(obj, (obj) => Annotation.set(obj, OrderAnnotation, { typeA: ['x'], typeB: ['m'] }));
|
|
568
|
+
|
|
569
|
+
Annotation.update(obj, OrderAnnotation, (order) => {
|
|
570
|
+
order.typeA.push('y');
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
expect(Option.getOrThrow(Annotation.get(obj, OrderAnnotation))).toEqual({ typeA: ['x', 'y'], typeB: ['m'] });
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
test('push a Ref to an annotation array in place', ({ expect }) => {
|
|
577
|
+
const obj = Obj.make(Container, { name: 'A' });
|
|
578
|
+
const a = Obj.make(Item, { name: 'a' });
|
|
579
|
+
const b = Obj.make(Item, { name: 'b' });
|
|
580
|
+
Obj.update(obj, (obj) => Annotation.set(obj, RefOrderAnnotation, { typeA: [Ref.make(a)] }));
|
|
581
|
+
|
|
582
|
+
Annotation.update(obj, RefOrderAnnotation, (order) => {
|
|
583
|
+
order.typeA.push(Ref.make(b));
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
const result = Annotation.get(obj, RefOrderAnnotation).pipe(Option.getOrThrow);
|
|
587
|
+
expect(result.typeA.map((ref) => ref.target?.id)).toEqual([a.id, b.id]);
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
test('atomProperty notifies subscribers when a Ref array is reordered in place', ({ expect }) => {
|
|
591
|
+
const registry = Registry.make();
|
|
592
|
+
const obj = Obj.make(Container, { name: 'A' });
|
|
593
|
+
const a = Obj.make(Item, { name: 'a' });
|
|
594
|
+
const b = Obj.make(Item, { name: 'b' });
|
|
595
|
+
const c = Obj.make(Item, { name: 'c' });
|
|
596
|
+
Obj.update(obj, (obj) =>
|
|
597
|
+
Annotation.set(obj, RefOrderAnnotation, { typeA: [Ref.make(a), Ref.make(b), Ref.make(c)] }),
|
|
598
|
+
);
|
|
599
|
+
|
|
600
|
+
const atomA = Annotation.atomProperty(obj, RefOrderAnnotation, 'typeA');
|
|
601
|
+
let fires = 0;
|
|
602
|
+
registry.subscribe(atomA, () => {
|
|
603
|
+
fires++;
|
|
604
|
+
});
|
|
605
|
+
registry.get(atomA);
|
|
606
|
+
|
|
607
|
+
Annotation.update(obj, RefOrderAnnotation, (order) => {
|
|
608
|
+
order.typeA.splice(0, order.typeA.length, Ref.make(c), Ref.make(a), Ref.make(b));
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
expect(fires).toBeGreaterThan(0);
|
|
612
|
+
// The atom emits a shallow snapshot of the ref array (refs kept intact).
|
|
613
|
+
expect(registry.get(atomA)?.map((ref) => ref.target?.id)).toEqual([c.id, a.id, b.id]);
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
test('reorder snapshot does not touch ref targets (tolerates cyclic targets)', ({ expect }) => {
|
|
617
|
+
const registry = Registry.make();
|
|
618
|
+
const obj = Obj.make(Container, { name: 'A' });
|
|
619
|
+
const a = Obj.make(Item, { name: 'a' });
|
|
620
|
+
// The annotation on `obj` holds a ref back to `obj`, so a loaded target forms a cycle —
|
|
621
|
+
// the shallow snapshot copies the array without dereferencing its ref elements, so it tolerates this.
|
|
622
|
+
Obj.update(obj, (obj) => Annotation.set(obj, RefOrderAnnotation, { typeA: [Ref.make(a), Ref.make(obj)] }));
|
|
623
|
+
|
|
624
|
+
const atomA = Annotation.atomProperty(obj, RefOrderAnnotation, 'typeA');
|
|
625
|
+
let fires = 0;
|
|
626
|
+
registry.subscribe(atomA, () => {
|
|
627
|
+
fires++;
|
|
628
|
+
});
|
|
629
|
+
registry.get(atomA);
|
|
630
|
+
|
|
631
|
+
Annotation.update(obj, RefOrderAnnotation, (order) => {
|
|
632
|
+
order.typeA.splice(0, order.typeA.length, Ref.make(obj), Ref.make(a));
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
expect(fires).toBeGreaterThan(0);
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
test('Annotation.update mutates in place (wraps its own change)', ({ expect }) => {
|
|
639
|
+
const registry = Registry.make();
|
|
640
|
+
const obj = Obj.make(Container, { name: 'A' });
|
|
641
|
+
Obj.update(obj, (obj) => Annotation.set(obj, OrderAnnotation, { typeA: ['x', 'y'] }));
|
|
642
|
+
|
|
643
|
+
const atomA = Annotation.atomProperty(obj, OrderAnnotation, 'typeA');
|
|
644
|
+
|
|
645
|
+
// No surrounding Obj.update — Annotation.update opens its own change transaction.
|
|
646
|
+
Annotation.update(obj, OrderAnnotation, (order) => {
|
|
647
|
+
order.typeA.push('z');
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
expect(registry.get(atomA)).toEqual(['x', 'y', 'z']);
|
|
651
|
+
});
|
|
652
|
+
|
|
653
|
+
test('Annotation.update is a no-op when the annotation is absent', ({ expect }) => {
|
|
654
|
+
const obj = Obj.make(Container, { name: 'A' });
|
|
655
|
+
let called = false;
|
|
656
|
+
Annotation.update(obj, OrderAnnotation, () => {
|
|
657
|
+
called = true;
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
expect(called).toBe(false);
|
|
661
|
+
expect(Option.isNone(Annotation.get(obj, OrderAnnotation))).toBe(true);
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
test('Annotation.update validates the mutated value against the annotation schema', ({ expect }) => {
|
|
665
|
+
const obj = Obj.make(Container, { name: 'A' });
|
|
666
|
+
Obj.update(obj, (obj) => Annotation.set(obj, OrderAnnotation, { typeA: ['x'] }));
|
|
667
|
+
|
|
668
|
+
expect(() =>
|
|
669
|
+
Annotation.update(obj, OrderAnnotation, (order) => {
|
|
670
|
+
// Pushing a number into a string array violates the annotation schema.
|
|
671
|
+
// @ts-expect-error intentional type violation to exercise runtime validation
|
|
672
|
+
order.typeA.push(42);
|
|
673
|
+
}),
|
|
674
|
+
).toThrow();
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
test('set validates the value against the annotation schema', ({ expect }) => {
|
|
678
|
+
const obj = Obj.make(Container, { name: 'A' });
|
|
679
|
+
Obj.update(obj, (obj) => {
|
|
680
|
+
// OrderAnnotation values must be string arrays; a number element violates the schema.
|
|
681
|
+
// @ts-expect-error intentional type violation to exercise runtime validation
|
|
682
|
+
expect(() => Annotation.set(obj, OrderAnnotation, { typeA: [1] })).toThrow();
|
|
683
|
+
});
|
|
684
|
+
});
|
|
685
|
+
});
|
|
439
686
|
});
|
package/src/Annotation.ts
CHANGED
|
@@ -5,18 +5,27 @@
|
|
|
5
5
|
// @import-as-namespace
|
|
6
6
|
|
|
7
7
|
export {
|
|
8
|
+
DEFAULT_LAYOUT_NAME,
|
|
8
9
|
DescriptionAnnotation,
|
|
9
10
|
FieldLookupAnnotationId,
|
|
10
|
-
|
|
11
|
+
FormCreateAnnotation,
|
|
12
|
+
FormCreateAnnotationId,
|
|
11
13
|
FormInlineAnnotation,
|
|
14
|
+
FormInputAnnotation,
|
|
15
|
+
FormLayoutAnnotation,
|
|
16
|
+
FormLayoutAnnotationId,
|
|
17
|
+
type FormLayoutMap,
|
|
18
|
+
FormOrderedAnnotation,
|
|
12
19
|
GeneratorAnnotation,
|
|
13
20
|
GeneratorAnnotationId,
|
|
14
21
|
type GeneratorAnnotationValue,
|
|
22
|
+
HiddenAnnotation,
|
|
23
|
+
IconAnnotation,
|
|
24
|
+
IconFromRefAnnotation,
|
|
15
25
|
LabelAnnotation,
|
|
16
26
|
ReferenceAnnotation,
|
|
17
27
|
ReferenceAnnotationId,
|
|
18
28
|
type ReferenceAnnotationValue,
|
|
19
|
-
HiddenAnnotation,
|
|
20
29
|
TypeAnnotation,
|
|
21
30
|
getDescriptionWithSchema,
|
|
22
31
|
getLabelWithSchema,
|
|
@@ -24,8 +33,6 @@ export {
|
|
|
24
33
|
getTypeIdentifierAnnotation,
|
|
25
34
|
setDescriptionWithSchema,
|
|
26
35
|
setLabelWithSchema,
|
|
27
|
-
IconAnnotation,
|
|
28
|
-
IconFromRefAnnotation,
|
|
29
36
|
} from './internal/Annotation';
|
|
30
37
|
|
|
31
38
|
import * as Function from 'effect/Function';
|
|
@@ -36,6 +43,7 @@ import * as Types from 'effect/Types';
|
|
|
36
43
|
|
|
37
44
|
import * as Entity from './Entity';
|
|
38
45
|
import * as internalAnnotations from './internal/Annotation';
|
|
46
|
+
import * as annotationAtoms from './internal/Annotation/atoms';
|
|
39
47
|
|
|
40
48
|
export const TypeId = '~@dxos/echo/Annotation' as const;
|
|
41
49
|
export type TypeId = typeof TypeId;
|
|
@@ -116,6 +124,11 @@ export const make: <T>(props: MakeProps<T>) => Annotation<T> = internalAnnotatio
|
|
|
116
124
|
* Get the value of an annotation from an entity instance or snapshot.
|
|
117
125
|
* For schema-level reads use the annotation instance method (e.g. `ColorAnnotation.get(schema)`).
|
|
118
126
|
* For getting an annotation value from a dictionary, use `getDictionary`.
|
|
127
|
+
*
|
|
128
|
+
* The value is read-only (schema types are readonly by default): to mutate an annotation (including
|
|
129
|
+
* in-place array splices) use `Annotation.update` or `Annotation.set`, which open a change transaction.
|
|
130
|
+
* A read-only return is sound regardless of context — the reactive proxy rejects mutation outside an
|
|
131
|
+
* `Obj.update`.
|
|
119
132
|
*/
|
|
120
133
|
export const get: {
|
|
121
134
|
<T>(annotation: Annotation<T>): (target: Entity.Unknown | Entity.Snapshot) => Option.Option<T>;
|
|
@@ -142,6 +155,18 @@ export const set: {
|
|
|
142
155
|
return internalAnnotations.set(target, annotation, value);
|
|
143
156
|
});
|
|
144
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Mutate an existing annotation value in place via a callback, wrapping the mutation in a change
|
|
160
|
+
* transaction (like `Obj.update`). The result is validated against the annotation's schema. Use when
|
|
161
|
+
* only an annotation needs to change; to mutate it alongside other changes (unvalidated), call
|
|
162
|
+
* `Annotation.get` inside an existing `Obj.update` instead. No-op when absent.
|
|
163
|
+
*/
|
|
164
|
+
export const update = <T>(
|
|
165
|
+
target: Entity.Unknown,
|
|
166
|
+
annotation: Annotation<T>,
|
|
167
|
+
mutator: (value: Entity.Mutable<T>) => void,
|
|
168
|
+
): void => internalAnnotations.update(target, annotation, mutator);
|
|
169
|
+
|
|
145
170
|
export const getFromAst: {
|
|
146
171
|
<T>(annotation: Annotation<T>): (ast: SchemaAST.AST) => Option.Option<T>;
|
|
147
172
|
<T>(ast: SchemaAST.AST, annotation: Annotation<T>): Option.Option<T>;
|
|
@@ -152,6 +177,18 @@ export const getFromAst: {
|
|
|
152
177
|
return internalAnnotations.getFromAst(ast, annotation);
|
|
153
178
|
});
|
|
154
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Reactive atom for an annotation value on an entity instance.
|
|
182
|
+
* Fires only when the annotation value changes (mirrors `Obj.atom`, scoped to one annotation).
|
|
183
|
+
*/
|
|
184
|
+
export const atom = annotationAtoms.makeAtom;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Reactive atom for a single key of a record-valued annotation on an entity instance.
|
|
188
|
+
* Reactivity is scoped to that key, and the value type is preserved (mirrors `Obj.atomProperty`).
|
|
189
|
+
*/
|
|
190
|
+
export const atomProperty = annotationAtoms.makeProperty;
|
|
191
|
+
|
|
155
192
|
/**
|
|
156
193
|
* Set of annotation values.
|
|
157
194
|
*
|
|
@@ -200,3 +237,20 @@ export const setDictionary: {
|
|
|
200
237
|
>(3, (values, annotation, value) => {
|
|
201
238
|
return internalAnnotations.setDictionary(values, annotation, value);
|
|
202
239
|
});
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Build a dictionary by mutating it in a callback.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* const dictionary = Annotation.buildDictionary((dictionary) => {
|
|
247
|
+
* Annotation.setDictionary(dictionary, ColorAnnotation, 'red');
|
|
248
|
+
* Annotation.setDictionary(dictionary, SizeAnnotation, '10px');
|
|
249
|
+
* });
|
|
250
|
+
* ```
|
|
251
|
+
*/
|
|
252
|
+
export const buildDictionary = (build: (dictionary: Types.Mutable<Dictionary>) => void): Dictionary => {
|
|
253
|
+
const dictionary = Schema.encodeSync(Dictionary)({});
|
|
254
|
+
build(dictionary);
|
|
255
|
+
return dictionary;
|
|
256
|
+
};
|
package/src/Collection.ts
CHANGED
|
@@ -17,17 +17,15 @@ import * as Type from './Type';
|
|
|
17
17
|
/**
|
|
18
18
|
* A an ordered set of objects.
|
|
19
19
|
*/
|
|
20
|
-
export
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
Annotation.IconAnnotation.set({ icon: 'ph--folder--regular', hue: '
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
export type Collection = Type.InstanceType<typeof Collection>;
|
|
29
|
-
|
|
30
|
-
export const make = (props: Partial<Obj.MakeProps<typeof Collection>> = {}): Collection =>
|
|
20
|
+
export class Collection extends Type.makeObject<Collection>(DXN.make('org.dxos.type.collection', '0.1.0'))(
|
|
21
|
+
Schema.Struct({
|
|
22
|
+
name: Schema.String.pipe(Schema.optional),
|
|
23
|
+
objects: Schema.Array(Ref.Ref(Obj.Unknown)).pipe(internal.FormInputAnnotation.set(false)),
|
|
24
|
+
}).pipe(Annotation.IconAnnotation.set({ icon: 'ph--folder--regular', hue: 'indigo' })),
|
|
25
|
+
) {}
|
|
26
|
+
|
|
27
|
+
export const make = (props: Partial<Obj.MakeProps<typeof Collection>> = {}): Type.InstanceType<typeof Collection> =>
|
|
31
28
|
Obj.make(Collection, { objects: [], ...props });
|
|
32
29
|
|
|
33
|
-
export const isCollection: (value: unknown) => value is Collection =
|
|
30
|
+
export const isCollection: (value: unknown) => value is Type.InstanceType<typeof Collection> =
|
|
31
|
+
Obj.instanceOf(Collection);
|
package/src/Database.ts
CHANGED
|
@@ -6,9 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import * as Context from 'effect/Context';
|
|
8
8
|
import * as Effect from 'effect/Effect';
|
|
9
|
-
import * as Effectable from 'effect/Effectable';
|
|
10
9
|
import * as Layer from 'effect/Layer';
|
|
11
|
-
import * as Option from 'effect/Option';
|
|
12
10
|
import * as Schema from 'effect/Schema';
|
|
13
11
|
|
|
14
12
|
import { EffectEx } from '@dxos/effect';
|
|
@@ -17,12 +15,14 @@ import { type SpaceId, type URI } from '@dxos/keys';
|
|
|
17
15
|
|
|
18
16
|
import type * as Entity from './Entity';
|
|
19
17
|
import * as Err from './Err';
|
|
18
|
+
import type * as Feed from './Feed';
|
|
20
19
|
import type * as Filter from './Filter';
|
|
21
20
|
import type * as Hypergraph from './Hypergraph';
|
|
22
21
|
import { type AnyProperties, EntityKind, KindId } from './internal/common/types';
|
|
23
22
|
// Deep import (not the `./internal/Entity` barrel) to avoid a cycle:
|
|
24
23
|
// Database → internal/Entity → entity → JsonSchema → Ref → Database.
|
|
25
24
|
import { isInstanceOf } from './internal/Entity/type-uri';
|
|
25
|
+
import * as queryInternal from './internal/Query';
|
|
26
26
|
import type { Ref } from './internal/Ref/ref';
|
|
27
27
|
import type * as Obj from './Obj';
|
|
28
28
|
import type * as Query from './Query';
|
|
@@ -166,11 +166,44 @@ export interface Database extends Queryable {
|
|
|
166
166
|
// TODO(burdon): Return true if removed (currently throws if not present).
|
|
167
167
|
remove(obj: Entity.Unknown): void;
|
|
168
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Appends entities to a feed.
|
|
171
|
+
*
|
|
172
|
+
* The feed must already be stored in the database (added via {@link add}); its underlying
|
|
173
|
+
* queue is addressed by the feed object's URI.
|
|
174
|
+
*/
|
|
175
|
+
appendToFeed(feed: Feed.Feed, entities: Entity.Unknown[]): Promise<void>;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Removes entities from a feed.
|
|
179
|
+
*/
|
|
180
|
+
deleteFromFeed(feed: Feed.Feed, entities: Entity.Unknown[]): Promise<void>;
|
|
181
|
+
|
|
169
182
|
/**
|
|
170
183
|
* Wait for all pending changes to be saved to disk.
|
|
171
184
|
* Optionaly waits for changes to be propagated to indexes and event handlers.
|
|
172
185
|
*/
|
|
173
186
|
flush(opts?: FlushOptions): Promise<void>;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Removes feed items by ID.
|
|
190
|
+
*/
|
|
191
|
+
removeFeedItemsByIds(feed: Feed.Feed, ids: string[]): Promise<void>;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Queries items in a feed associated with this database.
|
|
195
|
+
*/
|
|
196
|
+
queryFeed(feed: Feed.Feed, queryOrFilter: Query.Any | Filter.Any): QueryResult.QueryResult<any>;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Syncs a feed with the server.
|
|
200
|
+
*/
|
|
201
|
+
syncFeed(feed: Feed.Feed, options?: Feed.SyncOptions): Promise<void>;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Returns queue replication backlog for the feed's namespace.
|
|
205
|
+
*/
|
|
206
|
+
getFeedSyncState(feed: Feed.Feed): Promise<Feed.SyncState>;
|
|
174
207
|
}
|
|
175
208
|
|
|
176
209
|
export const isDatabase = (obj: unknown): obj is Database => {
|
|
@@ -250,7 +283,7 @@ export const resolve: {
|
|
|
250
283
|
space: db.spaceId,
|
|
251
284
|
},
|
|
252
285
|
})
|
|
253
|
-
.
|
|
286
|
+
.resolveLegacy(dxn),
|
|
254
287
|
);
|
|
255
288
|
|
|
256
289
|
if (!object) {
|
|
@@ -305,6 +338,24 @@ export const addType = <T extends Type.AnyEntity>(type: T): Effect.Effect<T, nev
|
|
|
305
338
|
export const remove = <T extends Entity.Unknown>(obj: T): Effect.Effect<void, never, Service> =>
|
|
306
339
|
Service.pipe(Effect.map(({ db }) => db.remove(obj))).pipe(Effect.withSpan('Database.remove'));
|
|
307
340
|
|
|
341
|
+
/**
|
|
342
|
+
* Appends entities to a feed.
|
|
343
|
+
* @see {@link Database.appendToFeed}
|
|
344
|
+
*/
|
|
345
|
+
export const appendToFeed = (feed: Feed.Feed, entities: Entity.Unknown[]): Effect.Effect<void, never, Service> =>
|
|
346
|
+
Service.pipe(
|
|
347
|
+
Effect.flatMap(({ db }) => EffectEx.promiseWithCauseCapture(() => db.appendToFeed(feed, entities))),
|
|
348
|
+
).pipe(Effect.withSpan('Database.appendToFeed'));
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Removes entities from a feed.
|
|
352
|
+
* @see {@link Database.deleteFromFeed}
|
|
353
|
+
*/
|
|
354
|
+
export const deleteFromFeed = (feed: Feed.Feed, entities: Entity.Unknown[]): Effect.Effect<void, never, Service> =>
|
|
355
|
+
Service.pipe(
|
|
356
|
+
Effect.flatMap(({ db }) => EffectEx.promiseWithCauseCapture(() => db.deleteFromFeed(feed, entities))),
|
|
357
|
+
).pipe(Effect.withSpan('Database.deleteFromFeed'));
|
|
358
|
+
|
|
308
359
|
/**
|
|
309
360
|
* Flushes pending changes to disk.
|
|
310
361
|
* @see {@link Database.flush}
|
|
@@ -324,22 +375,5 @@ export const query: {
|
|
|
324
375
|
Service.pipe(
|
|
325
376
|
Effect.map(({ db }) => db.query(queryOrFilter as any) as QueryResult.QueryResult<any>),
|
|
326
377
|
Effect.withSpan('Database.query'),
|
|
327
|
-
makeQueryResultEffect,
|
|
378
|
+
queryInternal.makeQueryResultEffect,
|
|
328
379
|
);
|
|
329
|
-
|
|
330
|
-
const makeQueryResultEffect = <T>(
|
|
331
|
-
eff: Effect.Effect<QueryResult.QueryResult<T>, never, Service>,
|
|
332
|
-
): QueryResult.QueryResultEffect<T, never, Service> => {
|
|
333
|
-
return {
|
|
334
|
-
run: Effect.flatMap(eff, (result) => EffectEx.promiseWithCauseCapture(() => result.run())),
|
|
335
|
-
first: Effect.flatMap(eff, (result) =>
|
|
336
|
-
EffectEx.promiseWithCauseCapture(async () => Option.fromNullable(await result.firstOrUndefined())),
|
|
337
|
-
),
|
|
338
|
-
|
|
339
|
-
// Effect internals
|
|
340
|
-
...Effectable.CommitPrototype,
|
|
341
|
-
commit() {
|
|
342
|
-
return eff;
|
|
343
|
-
},
|
|
344
|
-
} as any;
|
|
345
|
-
};
|
package/src/Entity.ts
CHANGED
|
@@ -190,7 +190,7 @@ export type AnyInput = Unknown | Snapshot;
|
|
|
190
190
|
* @param options.prefer - Controls the URI form (see {@link internal.GetURIOptions}).
|
|
191
191
|
*/
|
|
192
192
|
export const getURI = (entity: AnyInput, options?: internal.GetURIOptions): URI.URI =>
|
|
193
|
-
isTypeEntity(entity) ? Type.getURI(entity as Type.AnyEntity) : internal.getUri(entity as Unknown, options);
|
|
193
|
+
isTypeEntity(entity) ? Type.getURI(entity as Type.AnyEntity, options) : internal.getUri(entity as Unknown, options);
|
|
194
194
|
|
|
195
195
|
/**
|
|
196
196
|
* Get the DXN of an entity's type. For object/relation instances this is the URI
|
|
@@ -343,3 +343,5 @@ export const removeTag = (entity: Mutable<Unknown>, tag: Ref.Ref<Tag.Tag>): void
|
|
|
343
343
|
//
|
|
344
344
|
|
|
345
345
|
export const atom = objInternal.makeEntity;
|
|
346
|
+
export const labelAtom = objInternal.makeLabelAtom;
|
|
347
|
+
export const labelProperty = internal.getLabelProperty;
|
package/src/Err.ts
CHANGED
|
@@ -19,6 +19,28 @@ export class EntityNotFoundError extends BaseError.extend('EntityNotFoundError',
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Thrown when a `Text` mutation is attempted on an object whose reactive handler does not implement
|
|
24
|
+
* string CRDT editing (e.g. a snapshot or a non-reactive value).
|
|
25
|
+
*/
|
|
26
|
+
export class TextNotSupportedError extends BaseError.extend(
|
|
27
|
+
'TextNotSupportedError',
|
|
28
|
+
'Text operation is not supported for this object',
|
|
29
|
+
) {
|
|
30
|
+
constructor(operation: string, options?: BaseErrorOptions) {
|
|
31
|
+
super({ context: { operation }, ...options });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Thrown by `Text.apply` when a non-`replaceAll` edit's `oldString` is not found in the text.
|
|
37
|
+
*/
|
|
38
|
+
export class TextEditNotFoundError extends BaseError.extend('TextEditNotFoundError', 'Edit text not found') {
|
|
39
|
+
constructor(oldString: string, options?: BaseErrorOptions) {
|
|
40
|
+
super({ context: { oldString }, ...options });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
22
44
|
/**
|
|
23
45
|
* Reason why getting a reactive object from a snapshot failed.
|
|
24
46
|
* - `no-database`: The snapshot is not associated with a database.
|