@dxos/echo 0.8.4-main.67995b8 → 0.8.4-main.72ec0f3
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-BIDAASFK.mjs +3727 -0
- package/dist/lib/browser/chunk-BIDAASFK.mjs.map +7 -0
- package/dist/lib/browser/chunk-ZDLCWGEW.mjs +410 -0
- package/dist/lib/browser/chunk-ZDLCWGEW.mjs.map +7 -0
- package/dist/lib/browser/chunk-ZFRJKT4A.mjs +585 -0
- package/dist/lib/browser/chunk-ZFRJKT4A.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +17 -4
- package/dist/lib/browser/internal/index.mjs +336 -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 +13 -0
- package/dist/lib/browser/query/index.mjs.map +7 -0
- package/dist/lib/browser/testing/index.mjs +231 -34
- package/dist/lib/browser/testing/index.mjs.map +4 -4
- package/dist/lib/node-esm/chunk-3SVRRCUU.mjs +3727 -0
- package/dist/lib/node-esm/chunk-3SVRRCUU.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-CGDHRZWH.mjs +585 -0
- package/dist/lib/node-esm/chunk-CGDHRZWH.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-HWS6VBQC.mjs +410 -0
- package/dist/lib/node-esm/chunk-HWS6VBQC.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +17 -4
- package/dist/lib/node-esm/internal/index.mjs +336 -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 +13 -0
- package/dist/lib/node-esm/query/index.mjs.map +7 -0
- package/dist/lib/node-esm/testing/index.mjs +231 -34
- package/dist/lib/node-esm/testing/index.mjs.map +4 -4
- package/dist/types/src/Obj.d.ts +127 -19
- 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/Tag.d.ts +17 -0
- package/dist/types/src/Tag.d.ts.map +1 -0
- 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 +68 -0
- package/dist/types/src/errors.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +4 -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 +131 -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 +28 -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 +37 -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 +33 -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 +16 -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/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 +381 -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 +1 -1
- package/dist/types/src/query/index.d.ts.map +1 -1
- package/dist/types/src/query/{dsl.d.ts → query.d.ts} +52 -22
- 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/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 +170 -55
- package/dist/types/src/testing/types.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +40 -28
- package/src/Obj.ts +298 -29
- package/src/Ref.ts +1 -2
- package/src/Relation.ts +25 -13
- package/src/Tag.ts +39 -0
- package/src/Type.ts +32 -31
- package/src/errors.ts +18 -0
- package/src/index.ts +5 -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 +226 -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 +849 -0
- package/src/internal/json/json-schema.ts +519 -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 +153 -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 +248 -0
- package/src/internal/object/expando.ts +21 -0
- package/src/internal/object/ids.ts +12 -0
- package/src/internal/object/index.ts +19 -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 +61 -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 +88 -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 +92 -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 +144 -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/query.test.ts +401 -0
- package/src/query/{dsl.ts → query.ts} +188 -45
- 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 +40 -23
- 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
- package/src/query/dsl.test.ts +0 -323
|
@@ -2,20 +2,53 @@
|
|
|
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';
|
|
8
|
+
import type * as Types from 'effect/Types';
|
|
7
9
|
|
|
8
10
|
import { raise } from '@dxos/debug';
|
|
9
11
|
import { type ForeignKey, type QueryAST } from '@dxos/echo-protocol';
|
|
10
|
-
import { getTypeReference } from '@dxos/echo-schema';
|
|
11
12
|
import { assertArgument } from '@dxos/invariant';
|
|
12
13
|
import { DXN, ObjectId } from '@dxos/keys';
|
|
13
14
|
|
|
15
|
+
import { getTypeReference } from '../internal';
|
|
16
|
+
import type * as Obj from '../Obj';
|
|
14
17
|
import * as Ref from '../Ref';
|
|
15
18
|
import type * as Type from '../Type';
|
|
16
19
|
|
|
17
20
|
// TODO(dmaretskyi): Split up into interfaces for objects and relations so they can have separate verbs.
|
|
18
21
|
// TODO(dmaretskyi): Undirected relation traversals.
|
|
22
|
+
// TODO(wittjosiah): Make Filter & Query pipeable.
|
|
23
|
+
|
|
24
|
+
export interface Order<T> {
|
|
25
|
+
// TODO(dmaretskyi): See new effect-schema approach to variance.
|
|
26
|
+
'~Order': { value: T };
|
|
27
|
+
|
|
28
|
+
ast: QueryAST.Order;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
class OrderClass implements Order<any> {
|
|
32
|
+
private static variance: Order<any>['~Order'] = {} as Order<any>['~Order'];
|
|
33
|
+
|
|
34
|
+
static is(value: unknown): value is Order<any> {
|
|
35
|
+
return typeof value === 'object' && value !== null && '~Order' in value;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
constructor(public readonly ast: QueryAST.Order) {}
|
|
39
|
+
|
|
40
|
+
'~Order' = OrderClass.variance;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export namespace Order {
|
|
44
|
+
export const natural: Order<any> = new OrderClass({ kind: 'natural' });
|
|
45
|
+
export const property = <T>(property: keyof T & string, direction: QueryAST.OrderDirection): Order<T> =>
|
|
46
|
+
new OrderClass({
|
|
47
|
+
kind: 'property',
|
|
48
|
+
property,
|
|
49
|
+
direction,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
19
52
|
|
|
20
53
|
export interface Query<T> {
|
|
21
54
|
// TODO(dmaretskyi): See new effect-schema approach to variance.
|
|
@@ -33,10 +66,18 @@ export interface Query<T> {
|
|
|
33
66
|
|
|
34
67
|
/**
|
|
35
68
|
* Traverse an outgoing reference.
|
|
36
|
-
* @param key - Property path inside T that is a reference.
|
|
69
|
+
* @param key - Property path inside T that is a reference or optional reference.
|
|
37
70
|
* @returns Query for the target of the reference.
|
|
38
71
|
*/
|
|
39
|
-
reference<K extends RefPropKey<T>>(
|
|
72
|
+
reference<K extends RefPropKey<T>>(
|
|
73
|
+
key: K,
|
|
74
|
+
): Query<
|
|
75
|
+
T[K] extends Ref.Any
|
|
76
|
+
? Ref.Target<T[K]>
|
|
77
|
+
: T[K] extends Ref.Any | undefined
|
|
78
|
+
? Ref.Target<Exclude<T[K], undefined>>
|
|
79
|
+
: never
|
|
80
|
+
>;
|
|
40
81
|
|
|
41
82
|
/**
|
|
42
83
|
* Find objects referencing this object.
|
|
@@ -47,7 +88,7 @@ export interface Query<T> {
|
|
|
47
88
|
// TODO(dmaretskyi): any way to enforce `Ref.Target<Schema.Schema.Type<S>[key]> == T`?
|
|
48
89
|
// TODO(dmaretskyi): Ability to go through arrays of references.
|
|
49
90
|
referencedBy<S extends Schema.Schema.All>(
|
|
50
|
-
target: S,
|
|
91
|
+
target: S | string,
|
|
51
92
|
key: RefPropKey<Schema.Schema.Type<S>>,
|
|
52
93
|
): Query<Schema.Schema.Type<S>>;
|
|
53
94
|
|
|
@@ -58,7 +99,7 @@ export interface Query<T> {
|
|
|
58
99
|
* @param predicates - Predicates to filter the relation objects.
|
|
59
100
|
*/
|
|
60
101
|
sourceOf<S extends Schema.Schema.All>(
|
|
61
|
-
relation: S,
|
|
102
|
+
relation: S | string,
|
|
62
103
|
predicates?: Filter.Props<Schema.Schema.Type<S>>,
|
|
63
104
|
): Query<Schema.Schema.Type<S>>;
|
|
64
105
|
|
|
@@ -69,7 +110,7 @@ export interface Query<T> {
|
|
|
69
110
|
* @param predicates - Predicates to filter the relation objects.
|
|
70
111
|
*/
|
|
71
112
|
targetOf<S extends Schema.Schema.All>(
|
|
72
|
-
relation: S,
|
|
113
|
+
relation: S | string,
|
|
73
114
|
predicates?: Filter.Props<Schema.Schema.Type<S>>,
|
|
74
115
|
): Query<Schema.Schema.Type<S>>;
|
|
75
116
|
|
|
@@ -85,6 +126,14 @@ export interface Query<T> {
|
|
|
85
126
|
*/
|
|
86
127
|
target(): Query<Type.Relation.Target<T>>;
|
|
87
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Order the query results.
|
|
131
|
+
* Orders are specified in priority order. The first order will be applied first, etc.
|
|
132
|
+
* @param order - Order to sort the results.
|
|
133
|
+
* @returns Query for the ordered results.
|
|
134
|
+
*/
|
|
135
|
+
orderBy(...order: EffectArray.NonEmptyArray<Order<T>>): Query<T>;
|
|
136
|
+
|
|
88
137
|
/**
|
|
89
138
|
* Add options to a query.
|
|
90
139
|
*/
|
|
@@ -94,6 +143,9 @@ export interface Query<T> {
|
|
|
94
143
|
interface QueryAPI {
|
|
95
144
|
is(value: unknown): value is Query.Any;
|
|
96
145
|
|
|
146
|
+
/** Construct a query from an ast. */
|
|
147
|
+
fromAst(ast: QueryAST.Query): Query<any>;
|
|
148
|
+
|
|
97
149
|
/**
|
|
98
150
|
* Select objects based on a filter.
|
|
99
151
|
* @param filter - Filter to select the objects.
|
|
@@ -110,7 +162,7 @@ interface QueryAPI {
|
|
|
110
162
|
* Shorthand for: `Query.select(Filter.type(schema, predicates))`.
|
|
111
163
|
*/
|
|
112
164
|
type<S extends Schema.Schema.All>(
|
|
113
|
-
schema: S,
|
|
165
|
+
schema: S | string,
|
|
114
166
|
predicates?: Filter.Props<Schema.Schema.Type<S>>,
|
|
115
167
|
): Query<Schema.Schema.Type<S>>;
|
|
116
168
|
|
|
@@ -144,7 +196,7 @@ export declare namespace Query {
|
|
|
144
196
|
|
|
145
197
|
export interface Filter<T> {
|
|
146
198
|
// TODO(dmaretskyi): See new effect-schema approach to variance.
|
|
147
|
-
'~Filter': { value: T };
|
|
199
|
+
'~Filter': { value: Types.Contravariant<T> };
|
|
148
200
|
|
|
149
201
|
ast: QueryAST.Filter;
|
|
150
202
|
}
|
|
@@ -154,48 +206,56 @@ type Intersection<Types extends readonly unknown[]> = Types extends [infer First
|
|
|
154
206
|
: unknown;
|
|
155
207
|
|
|
156
208
|
interface FilterAPI {
|
|
157
|
-
is(value: unknown): value is Filter
|
|
209
|
+
is(value: unknown): value is Filter.Any;
|
|
210
|
+
|
|
211
|
+
/** Construct a filter from an ast. */
|
|
212
|
+
fromAst(ast: QueryAST.Filter): Filter<Obj.Any>;
|
|
158
213
|
|
|
159
214
|
/**
|
|
160
215
|
* Filter that matches all objects.
|
|
161
216
|
*/
|
|
162
|
-
|
|
217
|
+
// TODO(dmaretskyi): `Obj.Any` would be more type-safe, but causes annoying errors in existing code
|
|
218
|
+
everything(): Filter<Obj.AnyProps>;
|
|
163
219
|
|
|
164
220
|
/**
|
|
165
221
|
* Filter that matches no objects.
|
|
166
222
|
*/
|
|
223
|
+
// TODO(dmaretskyi): Filter<never>?
|
|
167
224
|
nothing(): Filter<any>;
|
|
168
225
|
|
|
169
226
|
/**
|
|
170
227
|
* Filter by object IDs.
|
|
171
228
|
*/
|
|
172
229
|
// TODO(dmaretskyi): Rename to `Filter.id`.
|
|
173
|
-
ids(...id: ObjectId[]): Filter<
|
|
230
|
+
ids(...id: ObjectId[]): Filter<Obj.AnyProps>;
|
|
174
231
|
|
|
175
232
|
/**
|
|
176
233
|
* Filter by type.
|
|
177
234
|
*/
|
|
178
235
|
type<S extends Schema.Schema.All>(
|
|
179
|
-
schema: S,
|
|
236
|
+
schema: S | string,
|
|
180
237
|
props?: Filter.Props<Schema.Schema.Type<S>>,
|
|
181
238
|
): Filter<Schema.Schema.Type<S>>;
|
|
182
239
|
|
|
183
240
|
/**
|
|
184
241
|
* Filter by non-qualified typename.
|
|
185
242
|
*/
|
|
186
|
-
typename(typename: string): Filter<
|
|
243
|
+
typename(typename: string): Filter<Obj.AnyProps>;
|
|
187
244
|
|
|
188
245
|
/**
|
|
189
246
|
* Filter by fully qualified type DXN.
|
|
190
247
|
*/
|
|
191
|
-
typeDXN(dxn: DXN): Filter<
|
|
248
|
+
typeDXN(dxn: DXN): Filter<Obj.AnyProps>;
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Filter by tag.
|
|
252
|
+
*/
|
|
253
|
+
tag(tag: string): Filter<Obj.Any>;
|
|
192
254
|
|
|
193
255
|
/**
|
|
194
256
|
* Filter by properties.
|
|
195
|
-
*
|
|
196
|
-
* INTERNAL API: Do not use.
|
|
197
257
|
*/
|
|
198
|
-
|
|
258
|
+
props<T>(props: Filter.Props<T>): Filter<T>;
|
|
199
259
|
|
|
200
260
|
/**
|
|
201
261
|
* Full-text or vector search.
|
|
@@ -252,12 +312,18 @@ interface FilterAPI {
|
|
|
252
312
|
*/
|
|
253
313
|
in<T>(...values: T[]): Filter<T>;
|
|
254
314
|
|
|
315
|
+
/**
|
|
316
|
+
* Predicate for an array property to contain the provided value.
|
|
317
|
+
* @param value - Value to check against.
|
|
318
|
+
*/
|
|
319
|
+
contains<T>(value: T): Filter<readonly T[] | undefined>;
|
|
320
|
+
|
|
255
321
|
/**
|
|
256
322
|
* Predicate for property to be in the provided range.
|
|
257
323
|
* @param from - Start of the range (inclusive).
|
|
258
324
|
* @param to - End of the range (exclusive).
|
|
259
325
|
*/
|
|
260
|
-
between<T>(from: T, to: T): Filter<
|
|
326
|
+
between<T>(from: T, to: T): Filter<unknown>;
|
|
261
327
|
|
|
262
328
|
/**
|
|
263
329
|
* Negate the filter.
|
|
@@ -287,11 +353,12 @@ export declare namespace Filter {
|
|
|
287
353
|
|
|
288
354
|
type Type<F extends Any> = F extends Filter<infer T> ? T : never;
|
|
289
355
|
|
|
290
|
-
type And<FS extends readonly Any[]> = Simplify<Intersection<{ [K in keyof FS]: Type<FS[K]> }>>;
|
|
356
|
+
type And<FS extends readonly Any[]> = Schema.Simplify<Intersection<{ [K in keyof FS]: Type<FS[K]> }>>;
|
|
291
357
|
|
|
292
|
-
type Or<FS extends readonly Any[]> = Simplify<{ [K in keyof FS]: Type<FS[K]> }[number]>;
|
|
358
|
+
type Or<FS extends readonly Any[]> = Schema.Simplify<{ [K in keyof FS]: Type<FS[K]> }[number]>;
|
|
293
359
|
}
|
|
294
360
|
|
|
361
|
+
// TODO(dmaretskyi): Separate object instead of statics for better devex with type errors.
|
|
295
362
|
class FilterClass implements Filter<any> {
|
|
296
363
|
private static variance: Filter<any>['~Filter'] = {} as Filter<any>['~Filter'];
|
|
297
364
|
|
|
@@ -299,6 +366,10 @@ class FilterClass implements Filter<any> {
|
|
|
299
366
|
return typeof value === 'object' && value !== null && '~Filter' in value;
|
|
300
367
|
}
|
|
301
368
|
|
|
369
|
+
static fromAst(ast: QueryAST.Filter): Filter<any> {
|
|
370
|
+
return new FilterClass(ast);
|
|
371
|
+
}
|
|
372
|
+
|
|
302
373
|
static everything(): FilterClass {
|
|
303
374
|
return new FilterClass({
|
|
304
375
|
type: 'object',
|
|
@@ -329,6 +400,7 @@ class FilterClass implements Filter<any> {
|
|
|
329
400
|
static ids(...ids: ObjectId[]): Filter<any> {
|
|
330
401
|
assertArgument(
|
|
331
402
|
ids.every((id) => ObjectId.isValid(id)),
|
|
403
|
+
'ids',
|
|
332
404
|
'ids must be valid',
|
|
333
405
|
);
|
|
334
406
|
|
|
@@ -345,10 +417,10 @@ class FilterClass implements Filter<any> {
|
|
|
345
417
|
}
|
|
346
418
|
|
|
347
419
|
static type<S extends Schema.Schema.All>(
|
|
348
|
-
schema: S,
|
|
420
|
+
schema: S | string,
|
|
349
421
|
props?: Filter.Props<Schema.Schema.Type<S>>,
|
|
350
422
|
): Filter<Schema.Schema.Type<S>> {
|
|
351
|
-
const dxn =
|
|
423
|
+
const dxn = getTypeDXNFromSpecifier(schema);
|
|
352
424
|
return new FilterClass({
|
|
353
425
|
type: 'object',
|
|
354
426
|
typename: dxn.toString(),
|
|
@@ -357,7 +429,7 @@ class FilterClass implements Filter<any> {
|
|
|
357
429
|
}
|
|
358
430
|
|
|
359
431
|
static typename(typename: string): Filter<any> {
|
|
360
|
-
assertArgument(!typename.startsWith('dxn:'), 'Typename must no be qualified');
|
|
432
|
+
assertArgument(!typename.startsWith('dxn:'), 'typename', 'Typename must no be qualified');
|
|
361
433
|
return new FilterClass({
|
|
362
434
|
type: 'object',
|
|
363
435
|
typename: DXN.fromTypename(typename).toString(),
|
|
@@ -373,10 +445,14 @@ class FilterClass implements Filter<any> {
|
|
|
373
445
|
});
|
|
374
446
|
}
|
|
375
447
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
448
|
+
static tag(tag: string): Filter<any> {
|
|
449
|
+
return new FilterClass({
|
|
450
|
+
type: 'tag',
|
|
451
|
+
tag,
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
static props<T>(props: Filter.Props<T>): Filter<T> {
|
|
380
456
|
return new FilterClass({
|
|
381
457
|
type: 'object',
|
|
382
458
|
typename: null,
|
|
@@ -392,8 +468,11 @@ class FilterClass implements Filter<any> {
|
|
|
392
468
|
});
|
|
393
469
|
}
|
|
394
470
|
|
|
395
|
-
static foreignKeys<S extends Schema.Schema.All>(
|
|
396
|
-
|
|
471
|
+
static foreignKeys<S extends Schema.Schema.All>(
|
|
472
|
+
schema: S | string,
|
|
473
|
+
keys: ForeignKey[],
|
|
474
|
+
): Filter<Schema.Schema.Type<S>> {
|
|
475
|
+
const dxn = getTypeDXNFromSpecifier(schema);
|
|
397
476
|
return new FilterClass({
|
|
398
477
|
type: 'object',
|
|
399
478
|
typename: dxn.toString(),
|
|
@@ -461,7 +540,14 @@ class FilterClass implements Filter<any> {
|
|
|
461
540
|
});
|
|
462
541
|
}
|
|
463
542
|
|
|
464
|
-
static
|
|
543
|
+
static contains<T>(value: T): Filter<readonly T[] | undefined> {
|
|
544
|
+
return new FilterClass({
|
|
545
|
+
type: 'contains',
|
|
546
|
+
value,
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
static between<T>(from: T, to: T): Filter<unknown> {
|
|
465
551
|
return new FilterClass({
|
|
466
552
|
type: 'range',
|
|
467
553
|
from,
|
|
@@ -506,7 +592,11 @@ type RefPropKey<T> = keyof T & string;
|
|
|
506
592
|
const propsFilterToAst = (predicates: Filter.Props<any>): Pick<QueryAST.FilterObject, 'id' | 'props'> => {
|
|
507
593
|
let idFilter: readonly ObjectId[] | undefined;
|
|
508
594
|
if ('id' in predicates) {
|
|
509
|
-
assertArgument(
|
|
595
|
+
assertArgument(
|
|
596
|
+
typeof predicates.id === 'string' || Array.isArray(predicates.id),
|
|
597
|
+
'predicates.id',
|
|
598
|
+
'invalid id filter',
|
|
599
|
+
);
|
|
510
600
|
idFilter = typeof predicates.id === 'string' ? [predicates.id] : predicates.id;
|
|
511
601
|
Schema.Array(ObjectId).pipe(Schema.validateSync)(idFilter);
|
|
512
602
|
}
|
|
@@ -516,11 +606,38 @@ const propsFilterToAst = (predicates: Filter.Props<any>): Pick<QueryAST.FilterOb
|
|
|
516
606
|
props: Object.fromEntries(
|
|
517
607
|
Object.entries(predicates)
|
|
518
608
|
.filter(([prop, _value]) => prop !== 'id')
|
|
519
|
-
.map(([prop, predicate]) => [prop,
|
|
609
|
+
.map(([prop, predicate]) => [prop, processPredicate(predicate)]),
|
|
520
610
|
) as Record<string, QueryAST.Filter>,
|
|
521
611
|
};
|
|
522
612
|
};
|
|
523
613
|
|
|
614
|
+
const processPredicate = (predicate: any): QueryAST.Filter => {
|
|
615
|
+
return Match.value(predicate).pipe(
|
|
616
|
+
Match.withReturnType<QueryAST.Filter>(),
|
|
617
|
+
Match.when(Filter.is, (predicate) => predicate.ast),
|
|
618
|
+
// TODO(wittjosiah): Add support for array predicates.
|
|
619
|
+
Match.when(Array.isArray, (_predicate) => {
|
|
620
|
+
throw new Error('Array predicates are not yet supported.');
|
|
621
|
+
}),
|
|
622
|
+
Match.when(
|
|
623
|
+
(predicate: any) => !Ref.isRef(predicate) && typeof predicate === 'object' && predicate !== null,
|
|
624
|
+
(predicate) => {
|
|
625
|
+
const nestedProps = Object.fromEntries(
|
|
626
|
+
Object.entries(predicate).map(([key, value]) => [key, processPredicate(value)]),
|
|
627
|
+
);
|
|
628
|
+
|
|
629
|
+
return {
|
|
630
|
+
type: 'object',
|
|
631
|
+
typename: null,
|
|
632
|
+
props: nestedProps,
|
|
633
|
+
};
|
|
634
|
+
},
|
|
635
|
+
),
|
|
636
|
+
Match.orElse((value) => Filter.eq(value).ast),
|
|
637
|
+
);
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
// TODO(dmaretskyi): Separate object instead of statics for better devex with type errors.
|
|
524
641
|
class QueryClass implements Query<any> {
|
|
525
642
|
private static variance: Query<any>['~Query'] = {} as Query<any>['~Query'];
|
|
526
643
|
|
|
@@ -528,6 +645,10 @@ class QueryClass implements Query<any> {
|
|
|
528
645
|
return typeof value === 'object' && value !== null && '~Query' in value;
|
|
529
646
|
}
|
|
530
647
|
|
|
648
|
+
static fromAst(ast: QueryAST.Query): Query<any> {
|
|
649
|
+
return new QueryClass(ast);
|
|
650
|
+
}
|
|
651
|
+
|
|
531
652
|
static select<F extends Filter.Any>(filter: F): Query<Filter.Type<F>> {
|
|
532
653
|
return new QueryClass({
|
|
533
654
|
type: 'select',
|
|
@@ -535,7 +656,7 @@ class QueryClass implements Query<any> {
|
|
|
535
656
|
});
|
|
536
657
|
}
|
|
537
658
|
|
|
538
|
-
static type(schema: Schema.Schema.All, predicates?: Filter.Props<unknown>): Query<any> {
|
|
659
|
+
static type(schema: Schema.Schema.All | string, predicates?: Filter.Props<unknown>): Query<any> {
|
|
539
660
|
return new QueryClass({
|
|
540
661
|
type: 'select',
|
|
541
662
|
filter: FilterClass.type(schema, predicates).ast,
|
|
@@ -566,7 +687,7 @@ class QueryClass implements Query<any> {
|
|
|
566
687
|
|
|
567
688
|
'~Query' = QueryClass.variance;
|
|
568
689
|
|
|
569
|
-
select(filter: Filter
|
|
690
|
+
select(filter: Filter.Any | Filter.Props<any>): Query.Any {
|
|
570
691
|
if (Filter.is(filter)) {
|
|
571
692
|
return new QueryClass({
|
|
572
693
|
type: 'filter',
|
|
@@ -577,12 +698,12 @@ class QueryClass implements Query<any> {
|
|
|
577
698
|
return new QueryClass({
|
|
578
699
|
type: 'filter',
|
|
579
700
|
selection: this.ast,
|
|
580
|
-
filter: FilterClass.
|
|
701
|
+
filter: FilterClass.props(filter).ast,
|
|
581
702
|
});
|
|
582
703
|
}
|
|
583
704
|
}
|
|
584
705
|
|
|
585
|
-
reference(key: string): Query
|
|
706
|
+
reference(key: string): Query.Any {
|
|
586
707
|
return new QueryClass({
|
|
587
708
|
type: 'reference-traversal',
|
|
588
709
|
anchor: this.ast,
|
|
@@ -590,8 +711,8 @@ class QueryClass implements Query<any> {
|
|
|
590
711
|
});
|
|
591
712
|
}
|
|
592
713
|
|
|
593
|
-
referencedBy(target: Schema.Schema.All, key: string): Query
|
|
594
|
-
const dxn =
|
|
714
|
+
referencedBy(target: Schema.Schema.All | string, key: string): Query.Any {
|
|
715
|
+
const dxn = getTypeDXNFromSpecifier(target);
|
|
595
716
|
return new QueryClass({
|
|
596
717
|
type: 'incoming-references',
|
|
597
718
|
anchor: this.ast,
|
|
@@ -600,7 +721,7 @@ class QueryClass implements Query<any> {
|
|
|
600
721
|
});
|
|
601
722
|
}
|
|
602
723
|
|
|
603
|
-
sourceOf(relation: Schema.Schema.All, predicates?: Filter.Props<unknown> | undefined): Query
|
|
724
|
+
sourceOf(relation: Schema.Schema.All | string, predicates?: Filter.Props<unknown> | undefined): Query.Any {
|
|
604
725
|
return new QueryClass({
|
|
605
726
|
type: 'relation',
|
|
606
727
|
anchor: this.ast,
|
|
@@ -609,7 +730,7 @@ class QueryClass implements Query<any> {
|
|
|
609
730
|
});
|
|
610
731
|
}
|
|
611
732
|
|
|
612
|
-
targetOf(relation: Schema.Schema.All, predicates?: Filter.Props<unknown> | undefined): Query
|
|
733
|
+
targetOf(relation: Schema.Schema.All | string, predicates?: Filter.Props<unknown> | undefined): Query.Any {
|
|
613
734
|
return new QueryClass({
|
|
614
735
|
type: 'relation',
|
|
615
736
|
anchor: this.ast,
|
|
@@ -618,7 +739,7 @@ class QueryClass implements Query<any> {
|
|
|
618
739
|
});
|
|
619
740
|
}
|
|
620
741
|
|
|
621
|
-
source(): Query
|
|
742
|
+
source(): Query.Any {
|
|
622
743
|
return new QueryClass({
|
|
623
744
|
type: 'relation-traversal',
|
|
624
745
|
anchor: this.ast,
|
|
@@ -626,7 +747,7 @@ class QueryClass implements Query<any> {
|
|
|
626
747
|
});
|
|
627
748
|
}
|
|
628
749
|
|
|
629
|
-
target(): Query
|
|
750
|
+
target(): Query.Any {
|
|
630
751
|
return new QueryClass({
|
|
631
752
|
type: 'relation-traversal',
|
|
632
753
|
anchor: this.ast,
|
|
@@ -634,7 +755,15 @@ class QueryClass implements Query<any> {
|
|
|
634
755
|
});
|
|
635
756
|
}
|
|
636
757
|
|
|
637
|
-
|
|
758
|
+
orderBy(...order: Order<any>[]): Query.Any {
|
|
759
|
+
return new QueryClass({
|
|
760
|
+
type: 'order',
|
|
761
|
+
query: this.ast,
|
|
762
|
+
order: order.map((o) => o.ast),
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
options(options: QueryAST.QueryOptions): Query.Any {
|
|
638
767
|
return new QueryClass({
|
|
639
768
|
type: 'options',
|
|
640
769
|
query: this.ast,
|
|
@@ -644,3 +773,17 @@ class QueryClass implements Query<any> {
|
|
|
644
773
|
}
|
|
645
774
|
|
|
646
775
|
export const Query: QueryAPI = QueryClass;
|
|
776
|
+
|
|
777
|
+
/**
|
|
778
|
+
* @param input schema or a typename string
|
|
779
|
+
* @return type DXN
|
|
780
|
+
*/
|
|
781
|
+
const getTypeDXNFromSpecifier = (input: Schema.Schema.All | string): DXN => {
|
|
782
|
+
if (Schema.isSchema(input)) {
|
|
783
|
+
return getTypeReference(input)?.toDXN() ?? raise(new TypeError('Schema has no DXN'));
|
|
784
|
+
} else {
|
|
785
|
+
assertArgument(typeof input === 'string', 'input');
|
|
786
|
+
assertArgument(!input.startsWith('dxn:'), 'input');
|
|
787
|
+
return DXN.fromTypename(input);
|
|
788
|
+
}
|
|
789
|
+
};
|
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
|
+
};
|