@dxos/echo 0.8.4-main.c1de068 → 0.8.4-main.c4373fc
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 +1 -1
- package/dist/lib/browser/chunk-MWLA34S5.mjs +3843 -0
- package/dist/lib/browser/chunk-MWLA34S5.mjs.map +7 -0
- package/dist/lib/browser/chunk-OAZJQHVO.mjs +453 -0
- package/dist/lib/browser/chunk-OAZJQHVO.mjs.map +7 -0
- package/dist/lib/browser/chunk-ORIE2FMS.mjs +514 -0
- package/dist/lib/browser/chunk-ORIE2FMS.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +26 -5
- package/dist/lib/browser/internal/index.mjs +326 -0
- package/dist/lib/browser/internal/index.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/query/index.mjs +23 -0
- package/dist/lib/browser/query/index.mjs.map +7 -0
- package/dist/lib/browser/testing/index.mjs +260 -32
- package/dist/lib/browser/testing/index.mjs.map +4 -4
- package/dist/lib/node-esm/chunk-AXWVDOP7.mjs +453 -0
- package/dist/lib/node-esm/chunk-AXWVDOP7.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-L4PBAJDP.mjs +514 -0
- package/dist/lib/node-esm/chunk-L4PBAJDP.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-YTNLFBIK.mjs +3843 -0
- package/dist/lib/node-esm/chunk-YTNLFBIK.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +26 -5
- package/dist/lib/node-esm/internal/index.mjs +326 -0
- package/dist/lib/node-esm/internal/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/query/index.mjs +23 -0
- package/dist/lib/node-esm/query/index.mjs.map +7 -0
- package/dist/lib/node-esm/testing/index.mjs +260 -32
- package/dist/lib/node-esm/testing/index.mjs.map +4 -4
- package/dist/types/src/Obj.d.ts +111 -17
- package/dist/types/src/Obj.d.ts.map +1 -1
- package/dist/types/src/Ref.d.ts +1 -1
- package/dist/types/src/Ref.d.ts.map +1 -1
- package/dist/types/src/Relation.d.ts +11 -8
- package/dist/types/src/Relation.d.ts.map +1 -1
- package/dist/types/src/Type.d.ts +17 -18
- package/dist/types/src/Type.d.ts.map +1 -1
- package/dist/types/src/errors.d.ts +72 -0
- package/dist/types/src/errors.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +3 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/internal/ast/annotation-helper.d.ts +8 -0
- package/dist/types/src/internal/ast/annotation-helper.d.ts.map +1 -0
- package/dist/types/src/internal/ast/annotations.d.ts +119 -0
- package/dist/types/src/internal/ast/annotations.d.ts.map +1 -0
- package/dist/types/src/internal/ast/annotations.test.d.ts +2 -0
- package/dist/types/src/internal/ast/annotations.test.d.ts.map +1 -0
- package/dist/types/src/internal/ast/entity-kind.d.ts +10 -0
- package/dist/types/src/internal/ast/entity-kind.d.ts.map +1 -0
- package/dist/types/src/internal/ast/index.d.ts +5 -0
- package/dist/types/src/internal/ast/index.d.ts.map +1 -0
- package/dist/types/src/internal/ast/types.d.ts +6 -0
- package/dist/types/src/internal/ast/types.d.ts.map +1 -0
- package/dist/types/src/internal/formats/date.d.ts +63 -0
- package/dist/types/src/internal/formats/date.d.ts.map +1 -0
- package/dist/types/src/internal/formats/date.test.d.ts +2 -0
- package/dist/types/src/internal/formats/date.test.d.ts.map +1 -0
- package/dist/types/src/internal/formats/format.d.ts +30 -0
- package/dist/types/src/internal/formats/format.d.ts.map +1 -0
- package/dist/types/src/internal/formats/format.test.d.ts +2 -0
- package/dist/types/src/internal/formats/format.test.d.ts.map +1 -0
- package/dist/types/src/internal/formats/index.d.ts +8 -0
- package/dist/types/src/internal/formats/index.d.ts.map +1 -0
- package/dist/types/src/internal/formats/number.d.ts +31 -0
- package/dist/types/src/internal/formats/number.d.ts.map +1 -0
- package/dist/types/src/internal/formats/object.d.ts +35 -0
- package/dist/types/src/internal/formats/object.d.ts.map +1 -0
- package/dist/types/src/internal/formats/select.d.ts +11 -0
- package/dist/types/src/internal/formats/select.d.ts.map +1 -0
- package/dist/types/src/internal/formats/string.d.ts +38 -0
- package/dist/types/src/internal/formats/string.d.ts.map +1 -0
- package/dist/types/src/internal/formats/types.d.ts +68 -0
- package/dist/types/src/internal/formats/types.d.ts.map +1 -0
- package/dist/types/src/internal/index.d.ts +15 -0
- package/dist/types/src/internal/index.d.ts.map +1 -0
- package/dist/types/src/internal/json/annotations.d.ts +19 -0
- package/dist/types/src/internal/json/annotations.d.ts.map +1 -0
- package/dist/types/src/internal/json/effect-schema.test.d.ts +2 -0
- package/dist/types/src/internal/json/effect-schema.test.d.ts.map +1 -0
- package/dist/types/src/internal/json/index.d.ts +2 -0
- package/dist/types/src/internal/json/index.d.ts.map +1 -0
- package/dist/types/src/internal/json/json-schema.d.ts +32 -0
- package/dist/types/src/internal/json/json-schema.d.ts.map +1 -0
- package/dist/types/src/internal/json/json-schema.test.d.ts +2 -0
- package/dist/types/src/internal/json/json-schema.test.d.ts.map +1 -0
- package/dist/types/src/internal/json-schema/index.d.ts +3 -0
- package/dist/types/src/internal/json-schema/index.d.ts.map +1 -0
- package/dist/types/src/internal/json-schema/json-schema-normalize.d.ts +7 -0
- package/dist/types/src/internal/json-schema/json-schema-normalize.d.ts.map +1 -0
- package/dist/types/src/internal/json-schema/json-schema-type.d.ts +250 -0
- package/dist/types/src/internal/json-schema/json-schema-type.d.ts.map +1 -0
- package/dist/types/src/internal/object/accessors.d.ts +29 -0
- package/dist/types/src/internal/object/accessors.d.ts.map +1 -0
- package/dist/types/src/internal/object/common.d.ts +18 -0
- package/dist/types/src/internal/object/common.d.ts.map +1 -0
- package/dist/types/src/internal/object/create.d.ts +40 -0
- package/dist/types/src/internal/object/create.d.ts.map +1 -0
- package/dist/types/src/internal/object/create.test.d.ts +2 -0
- package/dist/types/src/internal/object/create.test.d.ts.map +1 -0
- package/dist/types/src/internal/object/deleted.d.ts +6 -0
- package/dist/types/src/internal/object/deleted.d.ts.map +1 -0
- package/dist/types/src/internal/object/entity.d.ts +22 -0
- package/dist/types/src/internal/object/entity.d.ts.map +1 -0
- package/dist/types/src/internal/object/expando.d.ts +14 -0
- package/dist/types/src/internal/object/expando.d.ts.map +1 -0
- package/dist/types/src/internal/object/ids.d.ts +6 -0
- package/dist/types/src/internal/object/ids.d.ts.map +1 -0
- package/dist/types/src/internal/object/index.d.ts +17 -0
- package/dist/types/src/internal/object/index.d.ts.map +1 -0
- package/dist/types/src/internal/object/inspect.d.ts +2 -0
- package/dist/types/src/internal/object/inspect.d.ts.map +1 -0
- package/dist/types/src/internal/object/json-serializer.d.ts +32 -0
- package/dist/types/src/internal/object/json-serializer.d.ts.map +1 -0
- package/dist/types/src/internal/object/json-serializer.test.d.ts +2 -0
- package/dist/types/src/internal/object/json-serializer.test.d.ts.map +1 -0
- package/dist/types/src/internal/object/meta.d.ts +31 -0
- package/dist/types/src/internal/object/meta.d.ts.map +1 -0
- package/dist/types/src/internal/object/model.d.ts +117 -0
- package/dist/types/src/internal/object/model.d.ts.map +1 -0
- package/dist/types/src/internal/object/relation.d.ts +17 -0
- package/dist/types/src/internal/object/relation.d.ts.map +1 -0
- package/dist/types/src/internal/object/schema-validator.d.ts +15 -0
- package/dist/types/src/internal/object/schema-validator.d.ts.map +1 -0
- package/dist/types/src/internal/object/schema-validator.test.d.ts +2 -0
- package/dist/types/src/internal/object/schema-validator.test.d.ts.map +1 -0
- package/dist/types/src/internal/object/typed-object.d.ts +31 -0
- package/dist/types/src/internal/object/typed-object.d.ts.map +1 -0
- package/dist/types/src/internal/object/typed-object.test.d.ts +2 -0
- package/dist/types/src/internal/object/typed-object.test.d.ts.map +1 -0
- package/dist/types/src/internal/object/typed-relation.d.ts +32 -0
- package/dist/types/src/internal/object/typed-relation.d.ts.map +1 -0
- package/dist/types/src/internal/object/typename.d.ts +15 -0
- package/dist/types/src/internal/object/typename.d.ts.map +1 -0
- package/dist/types/src/internal/object/version.d.ts +14 -0
- package/dist/types/src/internal/object/version.d.ts.map +1 -0
- package/dist/types/src/internal/projection/compose.d.ts +6 -0
- package/dist/types/src/internal/projection/compose.d.ts.map +1 -0
- package/dist/types/src/internal/projection/compose.test.d.ts +2 -0
- package/dist/types/src/internal/projection/compose.test.d.ts.map +1 -0
- package/dist/types/src/internal/projection/index.d.ts +2 -0
- package/dist/types/src/internal/projection/index.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/handler.test.d.ts +2 -0
- package/dist/types/src/internal/proxy/handler.test.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/reactive-object.d.ts +15 -0
- package/dist/types/src/internal/proxy/reactive-object.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/schema.test.d.ts +2 -0
- package/dist/types/src/internal/proxy/schema.test.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/typed-handler.d.ts +44 -0
- package/dist/types/src/internal/proxy/typed-handler.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/typed-handler.test.d.ts +2 -0
- package/dist/types/src/internal/proxy/typed-handler.test.d.ts.map +1 -0
- package/dist/types/src/internal/proxy/typed-object.test.d.ts +2 -0
- package/dist/types/src/internal/proxy/typed-object.test.d.ts.map +1 -0
- package/dist/types/src/internal/query/index.d.ts +2 -0
- package/dist/types/src/internal/query/index.d.ts.map +1 -0
- package/dist/types/src/internal/query/query.d.ts +17 -0
- package/dist/types/src/internal/query/query.d.ts.map +1 -0
- package/dist/types/src/internal/ref/index.d.ts +3 -0
- package/dist/types/src/internal/ref/index.d.ts.map +1 -0
- package/dist/types/src/internal/ref/ref-array.d.ts +21 -0
- package/dist/types/src/internal/ref/ref-array.d.ts.map +1 -0
- package/dist/types/src/internal/ref/ref.d.ts +206 -0
- package/dist/types/src/internal/ref/ref.d.ts.map +1 -0
- package/dist/types/src/internal/ref/ref.test.d.ts +2 -0
- package/dist/types/src/internal/ref/ref.test.d.ts.map +1 -0
- package/dist/types/src/internal/schema/echo-schema.d.ts +168 -0
- package/dist/types/src/internal/schema/echo-schema.d.ts.map +1 -0
- package/dist/types/src/internal/schema/index.d.ts +7 -0
- package/dist/types/src/internal/schema/index.d.ts.map +1 -0
- package/dist/types/src/internal/schema/manipulation.d.ts +10 -0
- package/dist/types/src/internal/schema/manipulation.d.ts.map +1 -0
- package/dist/types/src/internal/schema/runtime-schema-registry.d.ts +18 -0
- package/dist/types/src/internal/schema/runtime-schema-registry.d.ts.map +1 -0
- package/dist/types/src/internal/schema/snapshot.d.ts +6 -0
- package/dist/types/src/internal/schema/snapshot.d.ts.map +1 -0
- package/dist/types/src/internal/schema/stored-schema.d.ts +13 -0
- package/dist/types/src/internal/schema/stored-schema.d.ts.map +1 -0
- package/dist/types/src/internal/testing/index.d.ts +3 -0
- package/dist/types/src/internal/testing/index.d.ts.map +1 -0
- package/dist/types/src/internal/testing/types.d.ts +455 -0
- package/dist/types/src/internal/testing/types.d.ts.map +1 -0
- package/dist/types/src/internal/testing/utils.d.ts +10 -0
- package/dist/types/src/internal/testing/utils.d.ts.map +1 -0
- package/dist/types/src/internal/types/index.d.ts +3 -0
- package/dist/types/src/internal/types/index.d.ts.map +1 -0
- package/dist/types/src/internal/types/types.d.ts +79 -0
- package/dist/types/src/internal/types/types.d.ts.map +1 -0
- package/dist/types/src/internal/types/types.test.d.ts +2 -0
- package/dist/types/src/internal/types/types.test.d.ts.map +1 -0
- package/dist/types/src/internal/types/util.d.ts +5 -0
- package/dist/types/src/internal/types/util.d.ts.map +1 -0
- package/dist/types/src/query/index.d.ts +2 -1
- package/dist/types/src/query/index.d.ts.map +1 -1
- package/dist/types/src/query/{dsl.d.ts → query.d.ts} +44 -15
- package/dist/types/src/query/query.d.ts.map +1 -0
- package/dist/types/src/query/query.test.d.ts +2 -0
- package/dist/types/src/query/query.test.d.ts.map +1 -0
- package/dist/types/src/query/tag.d.ts +18 -0
- package/dist/types/src/query/tag.d.ts.map +1 -0
- package/dist/types/src/testing/echo-schema.d.ts +7 -0
- package/dist/types/src/testing/echo-schema.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/types.d.ts +18 -18
- package/dist/types/src/testing/types.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +34 -16
- package/src/Obj.ts +250 -27
- package/src/Ref.ts +1 -2
- package/src/Relation.ts +25 -13
- package/src/Type.ts +32 -31
- package/src/errors.ts +18 -0
- package/src/index.ts +4 -1
- package/src/internal/ast/annotation-helper.ts +22 -0
- package/src/internal/ast/annotations.test.ts +98 -0
- package/src/internal/ast/annotations.ts +212 -0
- package/src/internal/ast/entity-kind.ts +15 -0
- package/src/internal/ast/index.ts +8 -0
- package/src/internal/ast/types.ts +17 -0
- package/src/internal/formats/date.test.ts +56 -0
- package/src/internal/formats/date.ts +217 -0
- package/src/internal/formats/format.test.ts +77 -0
- package/src/internal/formats/format.ts +52 -0
- package/src/internal/formats/index.ts +12 -0
- package/src/internal/formats/number.ts +89 -0
- package/src/internal/formats/object.ts +80 -0
- package/src/internal/formats/select.ts +16 -0
- package/src/internal/formats/string.ts +76 -0
- package/src/internal/formats/types.ts +175 -0
- package/src/internal/index.ts +22 -0
- package/src/internal/json/annotations.ts +50 -0
- package/src/internal/json/effect-schema.test.ts +143 -0
- package/src/internal/json/index.ts +5 -0
- package/src/internal/json/json-schema.test.ts +726 -0
- package/src/internal/json/json-schema.ts +548 -0
- package/src/internal/json-schema/index.ts +6 -0
- package/src/internal/json-schema/json-schema-normalize.ts +109 -0
- package/src/internal/json-schema/json-schema-type.ts +403 -0
- package/src/internal/object/accessors.ts +115 -0
- package/src/internal/object/common.ts +76 -0
- package/src/internal/object/create.test.ts +118 -0
- package/src/internal/object/create.ts +96 -0
- package/src/internal/object/deleted.ts +19 -0
- package/src/internal/object/entity.ts +204 -0
- package/src/internal/object/expando.ts +21 -0
- package/src/internal/object/ids.ts +12 -0
- package/src/internal/object/index.ts +20 -0
- package/src/internal/object/inspect.ts +48 -0
- package/src/internal/object/json-serializer.test.ts +99 -0
- package/src/internal/object/json-serializer.ts +225 -0
- package/src/internal/object/meta.ts +62 -0
- package/src/internal/object/model.ts +170 -0
- package/src/internal/object/relation.ts +24 -0
- package/src/internal/object/schema-validator.test.ts +186 -0
- package/src/internal/object/schema-validator.ts +241 -0
- package/src/internal/object/typed-object.test.ts +34 -0
- package/src/internal/object/typed-object.ts +81 -0
- package/src/internal/object/typed-relation.ts +85 -0
- package/src/internal/object/typename.ts +61 -0
- package/src/internal/object/version.ts +22 -0
- package/src/internal/projection/compose.test.ts +43 -0
- package/src/internal/projection/compose.ts +36 -0
- package/src/internal/projection/index.ts +5 -0
- package/src/internal/proxy/handler.test.ts +163 -0
- package/src/internal/proxy/reactive-object.ts +108 -0
- package/src/internal/proxy/schema.test.ts +136 -0
- package/src/internal/proxy/typed-handler.test.ts +102 -0
- package/src/internal/proxy/typed-handler.ts +228 -0
- package/src/internal/proxy/typed-object.test.ts +100 -0
- package/src/internal/query/index.ts +5 -0
- package/src/internal/query/query.ts +23 -0
- package/src/internal/ref/index.ts +6 -0
- package/src/internal/ref/ref-array.ts +39 -0
- package/src/internal/ref/ref.test.ts +100 -0
- package/src/internal/ref/ref.ts +521 -0
- package/src/internal/schema/echo-schema.ts +383 -0
- package/src/internal/schema/index.ts +10 -0
- package/src/internal/schema/manipulation.ts +86 -0
- package/src/internal/schema/runtime-schema-registry.ts +78 -0
- package/src/internal/schema/snapshot.ts +25 -0
- package/src/internal/schema/stored-schema.ts +26 -0
- package/src/internal/testing/index.ts +6 -0
- package/src/internal/testing/types.ts +211 -0
- package/src/internal/testing/utils.ts +54 -0
- package/src/internal/types/index.ts +6 -0
- package/src/internal/types/types.test.ts +48 -0
- package/src/internal/types/types.ts +176 -0
- package/src/internal/types/util.ts +9 -0
- package/src/query/index.ts +2 -1
- package/src/query/{dsl.test.ts → query.test.ts} +41 -2
- package/src/query/{dsl.ts → query.ts} +170 -32
- package/src/query/tag.ts +35 -0
- package/src/test/api.test.ts +17 -10
- package/src/testing/echo-schema.ts +39 -0
- package/src/testing/index.ts +2 -0
- package/src/testing/types.ts +1 -1
- package/dist/lib/browser/chunk-EUA7CM23.mjs +0 -619
- package/dist/lib/browser/chunk-EUA7CM23.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-IV6BWGHK.mjs +0 -619
- package/dist/lib/node-esm/chunk-IV6BWGHK.mjs.map +0 -7
- package/dist/types/src/experimental/database.d.ts +0 -8
- package/dist/types/src/experimental/database.d.ts.map +0 -1
- package/dist/types/src/experimental/index.d.ts +0 -1
- package/dist/types/src/experimental/index.d.ts.map +0 -1
- package/dist/types/src/experimental/queue.d.ts +0 -8
- package/dist/types/src/experimental/queue.d.ts.map +0 -1
- package/dist/types/src/experimental/space.d.ts +0 -8
- package/dist/types/src/experimental/space.d.ts.map +0 -1
- package/dist/types/src/query/dsl.d.ts.map +0 -1
- package/dist/types/src/query/dsl.test.d.ts +0 -2
- package/dist/types/src/query/dsl.test.d.ts.map +0 -1
- package/src/experimental/database.ts +0 -11
- package/src/experimental/index.ts +0 -7
- package/src/experimental/queue.ts +0 -11
- package/src/experimental/space.ts +0 -11
|
@@ -2,20 +2,52 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import type * as EffectArray from 'effect/Array';
|
|
6
|
+
import * as Match from 'effect/Match';
|
|
7
|
+
import * as Schema from 'effect/Schema';
|
|
7
8
|
|
|
8
9
|
import { raise } from '@dxos/debug';
|
|
9
10
|
import { type ForeignKey, type QueryAST } from '@dxos/echo-protocol';
|
|
10
|
-
import { getTypeReference } from '@dxos/echo-schema';
|
|
11
11
|
import { assertArgument } from '@dxos/invariant';
|
|
12
12
|
import { DXN, ObjectId } from '@dxos/keys';
|
|
13
13
|
|
|
14
|
+
import { getTypeReference } from '../internal';
|
|
15
|
+
import type * as Obj from '../Obj';
|
|
14
16
|
import * as Ref from '../Ref';
|
|
15
17
|
import type * as Type from '../Type';
|
|
16
18
|
|
|
17
19
|
// TODO(dmaretskyi): Split up into interfaces for objects and relations so they can have separate verbs.
|
|
18
20
|
// TODO(dmaretskyi): Undirected relation traversals.
|
|
21
|
+
// TODO(wittjosiah): Make Filter & Query pipeable.
|
|
22
|
+
|
|
23
|
+
export interface Order<T> {
|
|
24
|
+
// TODO(dmaretskyi): See new effect-schema approach to variance.
|
|
25
|
+
'~Order': { value: T };
|
|
26
|
+
|
|
27
|
+
ast: QueryAST.Order;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
class OrderClass implements Order<any> {
|
|
31
|
+
private static variance: Order<any>['~Order'] = {} as Order<any>['~Order'];
|
|
32
|
+
|
|
33
|
+
static is(value: unknown): value is Order<any> {
|
|
34
|
+
return typeof value === 'object' && value !== null && '~Order' in value;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
constructor(public readonly ast: QueryAST.Order) {}
|
|
38
|
+
|
|
39
|
+
'~Order' = OrderClass.variance;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export namespace Order {
|
|
43
|
+
export const natural: Order<any> = new OrderClass({ kind: 'natural' });
|
|
44
|
+
export const property = <T>(property: keyof T & string, direction: QueryAST.OrderDirection): Order<T> =>
|
|
45
|
+
new OrderClass({
|
|
46
|
+
kind: 'property',
|
|
47
|
+
property,
|
|
48
|
+
direction,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
19
51
|
|
|
20
52
|
export interface Query<T> {
|
|
21
53
|
// TODO(dmaretskyi): See new effect-schema approach to variance.
|
|
@@ -33,10 +65,18 @@ export interface Query<T> {
|
|
|
33
65
|
|
|
34
66
|
/**
|
|
35
67
|
* Traverse an outgoing reference.
|
|
36
|
-
* @param key - Property path inside T that is a reference.
|
|
68
|
+
* @param key - Property path inside T that is a reference or optional reference.
|
|
37
69
|
* @returns Query for the target of the reference.
|
|
38
70
|
*/
|
|
39
|
-
reference<K extends RefPropKey<T>>(
|
|
71
|
+
reference<K extends RefPropKey<T>>(
|
|
72
|
+
key: K,
|
|
73
|
+
): Query<
|
|
74
|
+
T[K] extends Ref.Any
|
|
75
|
+
? Ref.Target<T[K]>
|
|
76
|
+
: T[K] extends Ref.Any | undefined
|
|
77
|
+
? Ref.Target<Exclude<T[K], undefined>>
|
|
78
|
+
: never
|
|
79
|
+
>;
|
|
40
80
|
|
|
41
81
|
/**
|
|
42
82
|
* Find objects referencing this object.
|
|
@@ -47,7 +87,7 @@ export interface Query<T> {
|
|
|
47
87
|
// TODO(dmaretskyi): any way to enforce `Ref.Target<Schema.Schema.Type<S>[key]> == T`?
|
|
48
88
|
// TODO(dmaretskyi): Ability to go through arrays of references.
|
|
49
89
|
referencedBy<S extends Schema.Schema.All>(
|
|
50
|
-
target: S,
|
|
90
|
+
target: S | string,
|
|
51
91
|
key: RefPropKey<Schema.Schema.Type<S>>,
|
|
52
92
|
): Query<Schema.Schema.Type<S>>;
|
|
53
93
|
|
|
@@ -58,7 +98,7 @@ export interface Query<T> {
|
|
|
58
98
|
* @param predicates - Predicates to filter the relation objects.
|
|
59
99
|
*/
|
|
60
100
|
sourceOf<S extends Schema.Schema.All>(
|
|
61
|
-
relation: S,
|
|
101
|
+
relation: S | string,
|
|
62
102
|
predicates?: Filter.Props<Schema.Schema.Type<S>>,
|
|
63
103
|
): Query<Schema.Schema.Type<S>>;
|
|
64
104
|
|
|
@@ -69,7 +109,7 @@ export interface Query<T> {
|
|
|
69
109
|
* @param predicates - Predicates to filter the relation objects.
|
|
70
110
|
*/
|
|
71
111
|
targetOf<S extends Schema.Schema.All>(
|
|
72
|
-
relation: S,
|
|
112
|
+
relation: S | string,
|
|
73
113
|
predicates?: Filter.Props<Schema.Schema.Type<S>>,
|
|
74
114
|
): Query<Schema.Schema.Type<S>>;
|
|
75
115
|
|
|
@@ -85,6 +125,14 @@ export interface Query<T> {
|
|
|
85
125
|
*/
|
|
86
126
|
target(): Query<Type.Relation.Target<T>>;
|
|
87
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Order the query results.
|
|
130
|
+
* Orders are specified in priority order. The first order will be applied first, etc.
|
|
131
|
+
* @param order - Order to sort the results.
|
|
132
|
+
* @returns Query for the ordered results.
|
|
133
|
+
*/
|
|
134
|
+
orderBy(...order: EffectArray.NonEmptyArray<Order<T>>): Query<T>;
|
|
135
|
+
|
|
88
136
|
/**
|
|
89
137
|
* Add options to a query.
|
|
90
138
|
*/
|
|
@@ -94,6 +142,9 @@ export interface Query<T> {
|
|
|
94
142
|
interface QueryAPI {
|
|
95
143
|
is(value: unknown): value is Query.Any;
|
|
96
144
|
|
|
145
|
+
/** Construct a query from an ast. */
|
|
146
|
+
fromAst(ast: QueryAST.Query): Query<any>;
|
|
147
|
+
|
|
97
148
|
/**
|
|
98
149
|
* Select objects based on a filter.
|
|
99
150
|
* @param filter - Filter to select the objects.
|
|
@@ -110,7 +161,7 @@ interface QueryAPI {
|
|
|
110
161
|
* Shorthand for: `Query.select(Filter.type(schema, predicates))`.
|
|
111
162
|
*/
|
|
112
163
|
type<S extends Schema.Schema.All>(
|
|
113
|
-
schema: S,
|
|
164
|
+
schema: S | string,
|
|
114
165
|
predicates?: Filter.Props<Schema.Schema.Type<S>>,
|
|
115
166
|
): Query<Schema.Schema.Type<S>>;
|
|
116
167
|
|
|
@@ -156,6 +207,9 @@ type Intersection<Types extends readonly unknown[]> = Types extends [infer First
|
|
|
156
207
|
interface FilterAPI {
|
|
157
208
|
is(value: unknown): value is Filter<any>;
|
|
158
209
|
|
|
210
|
+
/** Construct a filter from an ast. */
|
|
211
|
+
fromAst(ast: QueryAST.Filter): Filter<any>;
|
|
212
|
+
|
|
159
213
|
/**
|
|
160
214
|
* Filter that matches all objects.
|
|
161
215
|
*/
|
|
@@ -176,7 +230,7 @@ interface FilterAPI {
|
|
|
176
230
|
* Filter by type.
|
|
177
231
|
*/
|
|
178
232
|
type<S extends Schema.Schema.All>(
|
|
179
|
-
schema: S,
|
|
233
|
+
schema: S | string,
|
|
180
234
|
props?: Filter.Props<Schema.Schema.Type<S>>,
|
|
181
235
|
): Filter<Schema.Schema.Type<S>>;
|
|
182
236
|
|
|
@@ -190,12 +244,15 @@ interface FilterAPI {
|
|
|
190
244
|
*/
|
|
191
245
|
typeDXN(dxn: DXN): Filter<any>;
|
|
192
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Filter by tag.
|
|
249
|
+
*/
|
|
250
|
+
tag(tag: string): Filter<Obj.Any>;
|
|
251
|
+
|
|
193
252
|
/**
|
|
194
253
|
* Filter by properties.
|
|
195
|
-
*
|
|
196
|
-
* INTERNAL API: Do not use.
|
|
197
254
|
*/
|
|
198
|
-
|
|
255
|
+
props<T>(props: Filter.Props<T>): Filter<T>;
|
|
199
256
|
|
|
200
257
|
/**
|
|
201
258
|
* Full-text or vector search.
|
|
@@ -252,6 +309,12 @@ interface FilterAPI {
|
|
|
252
309
|
*/
|
|
253
310
|
in<T>(...values: T[]): Filter<T>;
|
|
254
311
|
|
|
312
|
+
/**
|
|
313
|
+
* Predicate for an array property to contain the provided value.
|
|
314
|
+
* @param value - Value to check against.
|
|
315
|
+
*/
|
|
316
|
+
contains<T>(value: T): Filter<T[]>;
|
|
317
|
+
|
|
255
318
|
/**
|
|
256
319
|
* Predicate for property to be in the provided range.
|
|
257
320
|
* @param from - Start of the range (inclusive).
|
|
@@ -287,9 +350,9 @@ export declare namespace Filter {
|
|
|
287
350
|
|
|
288
351
|
type Type<F extends Any> = F extends Filter<infer T> ? T : never;
|
|
289
352
|
|
|
290
|
-
type And<FS extends readonly Any[]> = Simplify<Intersection<{ [K in keyof FS]: Type<FS[K]> }>>;
|
|
353
|
+
type And<FS extends readonly Any[]> = Schema.Simplify<Intersection<{ [K in keyof FS]: Type<FS[K]> }>>;
|
|
291
354
|
|
|
292
|
-
type Or<FS extends readonly Any[]> = Simplify<{ [K in keyof FS]: Type<FS[K]> }[number]>;
|
|
355
|
+
type Or<FS extends readonly Any[]> = Schema.Simplify<{ [K in keyof FS]: Type<FS[K]> }[number]>;
|
|
293
356
|
}
|
|
294
357
|
|
|
295
358
|
class FilterClass implements Filter<any> {
|
|
@@ -299,6 +362,10 @@ class FilterClass implements Filter<any> {
|
|
|
299
362
|
return typeof value === 'object' && value !== null && '~Filter' in value;
|
|
300
363
|
}
|
|
301
364
|
|
|
365
|
+
static fromAst(ast: QueryAST.Filter): Filter<any> {
|
|
366
|
+
return new FilterClass(ast);
|
|
367
|
+
}
|
|
368
|
+
|
|
302
369
|
static everything(): FilterClass {
|
|
303
370
|
return new FilterClass({
|
|
304
371
|
type: 'object',
|
|
@@ -329,6 +396,7 @@ class FilterClass implements Filter<any> {
|
|
|
329
396
|
static ids(...ids: ObjectId[]): Filter<any> {
|
|
330
397
|
assertArgument(
|
|
331
398
|
ids.every((id) => ObjectId.isValid(id)),
|
|
399
|
+
'ids',
|
|
332
400
|
'ids must be valid',
|
|
333
401
|
);
|
|
334
402
|
|
|
@@ -345,10 +413,10 @@ class FilterClass implements Filter<any> {
|
|
|
345
413
|
}
|
|
346
414
|
|
|
347
415
|
static type<S extends Schema.Schema.All>(
|
|
348
|
-
schema: S,
|
|
416
|
+
schema: S | string,
|
|
349
417
|
props?: Filter.Props<Schema.Schema.Type<S>>,
|
|
350
418
|
): Filter<Schema.Schema.Type<S>> {
|
|
351
|
-
const dxn =
|
|
419
|
+
const dxn = getTypeDXNFromSpecifier(schema);
|
|
352
420
|
return new FilterClass({
|
|
353
421
|
type: 'object',
|
|
354
422
|
typename: dxn.toString(),
|
|
@@ -357,7 +425,7 @@ class FilterClass implements Filter<any> {
|
|
|
357
425
|
}
|
|
358
426
|
|
|
359
427
|
static typename(typename: string): Filter<any> {
|
|
360
|
-
assertArgument(!typename.startsWith('dxn:'), 'Typename must no be qualified');
|
|
428
|
+
assertArgument(!typename.startsWith('dxn:'), 'typename', 'Typename must no be qualified');
|
|
361
429
|
return new FilterClass({
|
|
362
430
|
type: 'object',
|
|
363
431
|
typename: DXN.fromTypename(typename).toString(),
|
|
@@ -373,10 +441,14 @@ class FilterClass implements Filter<any> {
|
|
|
373
441
|
});
|
|
374
442
|
}
|
|
375
443
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
444
|
+
static tag(tag: string): Filter<any> {
|
|
445
|
+
return new FilterClass({
|
|
446
|
+
type: 'tag',
|
|
447
|
+
tag,
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
static props<T>(props: Filter.Props<T>): Filter<T> {
|
|
380
452
|
return new FilterClass({
|
|
381
453
|
type: 'object',
|
|
382
454
|
typename: null,
|
|
@@ -392,8 +464,11 @@ class FilterClass implements Filter<any> {
|
|
|
392
464
|
});
|
|
393
465
|
}
|
|
394
466
|
|
|
395
|
-
static foreignKeys<S extends Schema.Schema.All>(
|
|
396
|
-
|
|
467
|
+
static foreignKeys<S extends Schema.Schema.All>(
|
|
468
|
+
schema: S | string,
|
|
469
|
+
keys: ForeignKey[],
|
|
470
|
+
): Filter<Schema.Schema.Type<S>> {
|
|
471
|
+
const dxn = getTypeDXNFromSpecifier(schema);
|
|
397
472
|
return new FilterClass({
|
|
398
473
|
type: 'object',
|
|
399
474
|
typename: dxn.toString(),
|
|
@@ -461,6 +536,13 @@ class FilterClass implements Filter<any> {
|
|
|
461
536
|
});
|
|
462
537
|
}
|
|
463
538
|
|
|
539
|
+
static contains<T>(value: T): Filter<T[]> {
|
|
540
|
+
return new FilterClass({
|
|
541
|
+
type: 'contains',
|
|
542
|
+
value,
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
|
|
464
546
|
static between<T>(from: T, to: T): Filter<T> {
|
|
465
547
|
return new FilterClass({
|
|
466
548
|
type: 'range',
|
|
@@ -506,7 +588,11 @@ type RefPropKey<T> = keyof T & string;
|
|
|
506
588
|
const propsFilterToAst = (predicates: Filter.Props<any>): Pick<QueryAST.FilterObject, 'id' | 'props'> => {
|
|
507
589
|
let idFilter: readonly ObjectId[] | undefined;
|
|
508
590
|
if ('id' in predicates) {
|
|
509
|
-
assertArgument(
|
|
591
|
+
assertArgument(
|
|
592
|
+
typeof predicates.id === 'string' || Array.isArray(predicates.id),
|
|
593
|
+
'predicates.id',
|
|
594
|
+
'invalid id filter',
|
|
595
|
+
);
|
|
510
596
|
idFilter = typeof predicates.id === 'string' ? [predicates.id] : predicates.id;
|
|
511
597
|
Schema.Array(ObjectId).pipe(Schema.validateSync)(idFilter);
|
|
512
598
|
}
|
|
@@ -516,11 +602,37 @@ const propsFilterToAst = (predicates: Filter.Props<any>): Pick<QueryAST.FilterOb
|
|
|
516
602
|
props: Object.fromEntries(
|
|
517
603
|
Object.entries(predicates)
|
|
518
604
|
.filter(([prop, _value]) => prop !== 'id')
|
|
519
|
-
.map(([prop, predicate]) => [prop,
|
|
605
|
+
.map(([prop, predicate]) => [prop, processPredicate(predicate)]),
|
|
520
606
|
) as Record<string, QueryAST.Filter>,
|
|
521
607
|
};
|
|
522
608
|
};
|
|
523
609
|
|
|
610
|
+
const processPredicate = (predicate: any): QueryAST.Filter => {
|
|
611
|
+
return Match.value(predicate).pipe(
|
|
612
|
+
Match.withReturnType<QueryAST.Filter>(),
|
|
613
|
+
Match.when(Filter.is, (predicate) => predicate.ast),
|
|
614
|
+
// TODO(wittjosiah): Add support for array predicates.
|
|
615
|
+
Match.when(Array.isArray, (_predicate) => {
|
|
616
|
+
throw new Error('Array predicates are not yet supported.');
|
|
617
|
+
}),
|
|
618
|
+
Match.when(
|
|
619
|
+
(predicate: any) => !Ref.isRef(predicate) && typeof predicate === 'object' && predicate !== null,
|
|
620
|
+
(predicate) => {
|
|
621
|
+
const nestedProps = Object.fromEntries(
|
|
622
|
+
Object.entries(predicate).map(([key, value]) => [key, processPredicate(value)]),
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
return {
|
|
626
|
+
type: 'object',
|
|
627
|
+
typename: null,
|
|
628
|
+
props: nestedProps,
|
|
629
|
+
};
|
|
630
|
+
},
|
|
631
|
+
),
|
|
632
|
+
Match.orElse((value) => Filter.eq(value).ast),
|
|
633
|
+
);
|
|
634
|
+
};
|
|
635
|
+
|
|
524
636
|
class QueryClass implements Query<any> {
|
|
525
637
|
private static variance: Query<any>['~Query'] = {} as Query<any>['~Query'];
|
|
526
638
|
|
|
@@ -528,6 +640,10 @@ class QueryClass implements Query<any> {
|
|
|
528
640
|
return typeof value === 'object' && value !== null && '~Query' in value;
|
|
529
641
|
}
|
|
530
642
|
|
|
643
|
+
static fromAst(ast: QueryAST.Query): Query<any> {
|
|
644
|
+
return new QueryClass(ast);
|
|
645
|
+
}
|
|
646
|
+
|
|
531
647
|
static select<F extends Filter.Any>(filter: F): Query<Filter.Type<F>> {
|
|
532
648
|
return new QueryClass({
|
|
533
649
|
type: 'select',
|
|
@@ -535,7 +651,7 @@ class QueryClass implements Query<any> {
|
|
|
535
651
|
});
|
|
536
652
|
}
|
|
537
653
|
|
|
538
|
-
static type(schema: Schema.Schema.All, predicates?: Filter.Props<unknown>): Query<any> {
|
|
654
|
+
static type(schema: Schema.Schema.All | string, predicates?: Filter.Props<unknown>): Query<any> {
|
|
539
655
|
return new QueryClass({
|
|
540
656
|
type: 'select',
|
|
541
657
|
filter: FilterClass.type(schema, predicates).ast,
|
|
@@ -577,7 +693,7 @@ class QueryClass implements Query<any> {
|
|
|
577
693
|
return new QueryClass({
|
|
578
694
|
type: 'filter',
|
|
579
695
|
selection: this.ast,
|
|
580
|
-
filter: FilterClass.
|
|
696
|
+
filter: FilterClass.props(filter).ast,
|
|
581
697
|
});
|
|
582
698
|
}
|
|
583
699
|
}
|
|
@@ -590,8 +706,8 @@ class QueryClass implements Query<any> {
|
|
|
590
706
|
});
|
|
591
707
|
}
|
|
592
708
|
|
|
593
|
-
referencedBy(target: Schema.Schema.All, key: string): Query<any> {
|
|
594
|
-
const dxn =
|
|
709
|
+
referencedBy(target: Schema.Schema.All | string, key: string): Query<any> {
|
|
710
|
+
const dxn = getTypeDXNFromSpecifier(target);
|
|
595
711
|
return new QueryClass({
|
|
596
712
|
type: 'incoming-references',
|
|
597
713
|
anchor: this.ast,
|
|
@@ -600,7 +716,7 @@ class QueryClass implements Query<any> {
|
|
|
600
716
|
});
|
|
601
717
|
}
|
|
602
718
|
|
|
603
|
-
sourceOf(relation: Schema.Schema.All, predicates?: Filter.Props<unknown> | undefined): Query<any> {
|
|
719
|
+
sourceOf(relation: Schema.Schema.All | string, predicates?: Filter.Props<unknown> | undefined): Query<any> {
|
|
604
720
|
return new QueryClass({
|
|
605
721
|
type: 'relation',
|
|
606
722
|
anchor: this.ast,
|
|
@@ -609,7 +725,7 @@ class QueryClass implements Query<any> {
|
|
|
609
725
|
});
|
|
610
726
|
}
|
|
611
727
|
|
|
612
|
-
targetOf(relation: Schema.Schema.All, predicates?: Filter.Props<unknown> | undefined): Query<any> {
|
|
728
|
+
targetOf(relation: Schema.Schema.All | string, predicates?: Filter.Props<unknown> | undefined): Query<any> {
|
|
613
729
|
return new QueryClass({
|
|
614
730
|
type: 'relation',
|
|
615
731
|
anchor: this.ast,
|
|
@@ -634,6 +750,14 @@ class QueryClass implements Query<any> {
|
|
|
634
750
|
});
|
|
635
751
|
}
|
|
636
752
|
|
|
753
|
+
orderBy(...order: Order<any>[]): Query<any> {
|
|
754
|
+
return new QueryClass({
|
|
755
|
+
type: 'order',
|
|
756
|
+
query: this.ast,
|
|
757
|
+
order: order.map((o) => o.ast),
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
|
|
637
761
|
options(options: QueryAST.QueryOptions): Query<any> {
|
|
638
762
|
return new QueryClass({
|
|
639
763
|
type: 'options',
|
|
@@ -644,3 +768,17 @@ class QueryClass implements Query<any> {
|
|
|
644
768
|
}
|
|
645
769
|
|
|
646
770
|
export const Query: QueryAPI = QueryClass;
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* @param input schema or a typename string
|
|
774
|
+
* @return type DXN
|
|
775
|
+
*/
|
|
776
|
+
const getTypeDXNFromSpecifier = (input: Schema.Schema.All | string): DXN => {
|
|
777
|
+
if (Schema.isSchema(input)) {
|
|
778
|
+
return getTypeReference(input)?.toDXN() ?? raise(new TypeError('Schema has no DXN'));
|
|
779
|
+
} else {
|
|
780
|
+
assertArgument(typeof input === 'string', 'input');
|
|
781
|
+
assertArgument(!input.startsWith('dxn:'), 'input');
|
|
782
|
+
return DXN.fromTypename(input);
|
|
783
|
+
}
|
|
784
|
+
};
|
package/src/query/tag.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Schema from 'effect/Schema';
|
|
6
|
+
|
|
7
|
+
export const TagInfo = Schema.Struct({
|
|
8
|
+
label: Schema.String,
|
|
9
|
+
hue: Schema.optional(Schema.String), // TODO(burdon): Color name?
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export type TagInfo = Schema.Schema.Type<typeof TagInfo>;
|
|
13
|
+
|
|
14
|
+
export const Tag = Schema.extend(
|
|
15
|
+
TagInfo,
|
|
16
|
+
Schema.Struct({
|
|
17
|
+
id: Schema.String,
|
|
18
|
+
}),
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export type Tag = Schema.Schema.Type<typeof Tag>;
|
|
22
|
+
|
|
23
|
+
export type TagMap = Record<string, TagInfo>;
|
|
24
|
+
|
|
25
|
+
export const sortTags = ({ label: a }: TagInfo, { label: b }: TagInfo) => a.localeCompare(b);
|
|
26
|
+
|
|
27
|
+
export const createTagList = (tags: TagMap): Tag[] =>
|
|
28
|
+
Object.entries(tags)
|
|
29
|
+
.map(([id, tag]) => ({ ...tag, id }))
|
|
30
|
+
.sort(sortTags);
|
|
31
|
+
|
|
32
|
+
export const findTagByLabel = (tags: Record<string, TagInfo> | undefined, name: string): Tag | undefined => {
|
|
33
|
+
const entry = Object.entries(tags ?? {}).find(([_, tag]) => tag.label.toLowerCase() === name.toLowerCase());
|
|
34
|
+
return entry ? { ...entry[1], id: entry[0] } : undefined;
|
|
35
|
+
};
|
package/src/test/api.test.ts
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import * as Schema from 'effect/Schema';
|
|
6
6
|
import { describe, test } from 'vitest';
|
|
7
7
|
|
|
8
8
|
import { raise } from '@dxos/debug';
|
|
9
|
-
import {
|
|
9
|
+
import { FormatAnnotation, FormatEnum } from '@dxos/echo/internal';
|
|
10
10
|
|
|
11
|
-
import { Obj, Ref, Relation, Type
|
|
11
|
+
import { type Live, Obj, Ref, Relation, Type } from '../index';
|
|
12
12
|
|
|
13
13
|
namespace Testing {
|
|
14
14
|
export const Organization = Schema.Struct({
|
|
@@ -151,22 +151,29 @@ describe('Experimental API review', () => {
|
|
|
151
151
|
expect(Relation.getTarget(worksFor)).to.eq(organization);
|
|
152
152
|
});
|
|
153
153
|
|
|
154
|
+
test('version', ({ expect }) => {
|
|
155
|
+
const person = Obj.make(Testing.Person, { name: 'Test' });
|
|
156
|
+
const version = Obj.version(person);
|
|
157
|
+
expect(Obj.isVersion(version)).to.be.true;
|
|
158
|
+
expect(Obj.versionValid(version)).to.be.false;
|
|
159
|
+
});
|
|
160
|
+
|
|
154
161
|
test.skip('type narrowing', () => {
|
|
155
|
-
const
|
|
162
|
+
const any: Obj.Any | Relation.Any = null as any;
|
|
156
163
|
|
|
157
164
|
{
|
|
158
|
-
if (Obj.isObject(
|
|
159
|
-
|
|
165
|
+
if (Obj.isObject(any)) {
|
|
166
|
+
any;
|
|
160
167
|
} else {
|
|
161
|
-
|
|
168
|
+
any;
|
|
162
169
|
}
|
|
163
170
|
}
|
|
164
171
|
|
|
165
172
|
{
|
|
166
|
-
if (Relation.isRelation(
|
|
167
|
-
|
|
173
|
+
if (Relation.isRelation(any)) {
|
|
174
|
+
any;
|
|
168
175
|
} else {
|
|
169
|
-
|
|
176
|
+
any;
|
|
170
177
|
}
|
|
171
178
|
}
|
|
172
179
|
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { effect } from '@preact/signals-core';
|
|
6
|
+
import type * as Schema from 'effect/Schema';
|
|
7
|
+
|
|
8
|
+
import { registerSignalsRuntime } from '@dxos/echo-signals';
|
|
9
|
+
import { assertArgument } from '@dxos/invariant';
|
|
10
|
+
|
|
11
|
+
import { EchoSchema, StoredSchema, getSchemaTypename, live, toJsonSchema } from '../internal';
|
|
12
|
+
|
|
13
|
+
// NOTE: Registration is done here is this is the module that calls out to `effect`.
|
|
14
|
+
registerSignalsRuntime();
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Create a reactive mutable schema that updates when the JSON schema is updated.
|
|
18
|
+
*/
|
|
19
|
+
// TODO(dmaretskyi): Should be replaced by registration of typed object.
|
|
20
|
+
export const createEchoSchema = (schema: Schema.Schema.AnyNoContext): EchoSchema => {
|
|
21
|
+
const typename = getSchemaTypename(schema);
|
|
22
|
+
assertArgument(typename, 'typename', 'Schema does not have a typename.');
|
|
23
|
+
|
|
24
|
+
const echoSchema = new EchoSchema(
|
|
25
|
+
live(StoredSchema, {
|
|
26
|
+
typename,
|
|
27
|
+
version: '0.1.0',
|
|
28
|
+
jsonSchema: toJsonSchema(schema),
|
|
29
|
+
}),
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// TODO(burdon): Unsubscribe is never called.
|
|
33
|
+
effect(() => {
|
|
34
|
+
const _ = echoSchema.jsonSchema;
|
|
35
|
+
echoSchema._invalidate();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return echoSchema;
|
|
39
|
+
};
|
package/src/testing/index.ts
CHANGED