@dxos/echo 0.8.4-main.e098934 → 0.8.4-main.ead640a
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/browser/chunk-HKFCK2GL.mjs +175 -0
- package/dist/lib/browser/chunk-HKFCK2GL.mjs.map +7 -0
- package/dist/lib/browser/{chunk-EIXXFUN5.mjs → chunk-MAAYELT7.mjs} +477 -486
- package/dist/lib/browser/chunk-MAAYELT7.mjs.map +7 -0
- package/dist/lib/browser/chunk-MB6MMNFP.mjs +3857 -0
- package/dist/lib/browser/chunk-MB6MMNFP.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +12 -7
- package/dist/lib/browser/internal/index.mjs +332 -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 +15 -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-TCY7IVTS.mjs → chunk-5NWDGIBT.mjs} +477 -486
- package/dist/lib/node-esm/chunk-5NWDGIBT.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-AUAH4E2J.mjs +175 -0
- package/dist/lib/node-esm/chunk-AUAH4E2J.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-BQRA4VLX.mjs +3857 -0
- package/dist/lib/node-esm/chunk-BQRA4VLX.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +12 -7
- package/dist/lib/node-esm/internal/index.mjs +332 -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 +15 -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 +22 -5
- 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 +5 -4
- package/dist/types/src/Relation.d.ts.map +1 -1
- package/dist/types/src/Type.d.ts +16 -17
- package/dist/types/src/Type.d.ts.map +1 -1
- package/dist/types/src/errors.d.ts +8 -8
- package/dist/types/src/index.d.ts +2 -2
- 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 +125 -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 +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} +28 -23
- 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 +17 -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 +29 -18
- package/src/Obj.ts +77 -12
- package/src/Ref.ts +1 -2
- package/src/Relation.ts +15 -5
- package/src/Type.ts +29 -30
- package/src/index.ts +2 -2
- package/src/internal/ast/annotation-helper.ts +22 -0
- package/src/internal/ast/annotations.test.ts +98 -0
- package/src/internal/ast/annotations.ts +219 -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 +857 -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 +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/query.test.ts +401 -0
- package/src/query/{dsl.ts → query.ts} +82 -45
- package/src/query/tag.ts +37 -0
- package/src/test/api.test.ts +9 -9
- 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-EIXXFUN5.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-TCY7IVTS.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 -362
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Schema from 'effect/Schema';
|
|
6
|
+
|
|
7
|
+
import { JsonPath, type JsonProp } from '@dxos/effect';
|
|
8
|
+
|
|
9
|
+
import { EntityKindSchema } from '../ast';
|
|
10
|
+
import { FormatAnnotation, FormatEnum } from '../formats';
|
|
11
|
+
|
|
12
|
+
//
|
|
13
|
+
// JSON Schema
|
|
14
|
+
//
|
|
15
|
+
|
|
16
|
+
// TODO(burdon): Reuse/reconcile with ScalarTypeEnum (handle arrays).
|
|
17
|
+
const SimpleTypes = Schema.Literal('array', 'boolean', 'integer', 'null', 'number', 'object', 'string');
|
|
18
|
+
|
|
19
|
+
const NonNegativeInteger = Schema.Number.pipe(Schema.greaterThanOrEqualTo(0));
|
|
20
|
+
|
|
21
|
+
const StringArray = Schema.Array(Schema.String).pipe(Schema.mutable);
|
|
22
|
+
|
|
23
|
+
const JsonSchemaOrBoolean = Schema.Union(
|
|
24
|
+
Schema.suspend(() => JsonSchemaType),
|
|
25
|
+
Schema.Boolean,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Go under the `annotations` property.
|
|
30
|
+
*/
|
|
31
|
+
export const JsonSchemaEchoAnnotations = Schema.Struct({
|
|
32
|
+
/**
|
|
33
|
+
* Label for this schema.
|
|
34
|
+
* Mapped from {@link LabelAnnotationId}.
|
|
35
|
+
*/
|
|
36
|
+
labelProp: Schema.optional(Schema.Union(JsonPath, Schema.Array(JsonPath))),
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Generator function for this schema.
|
|
40
|
+
* Mapped from {@link GeneratorAnnotationId}.
|
|
41
|
+
*/
|
|
42
|
+
generator: Schema.optional(Schema.Union(Schema.String, Schema.Tuple(Schema.String, Schema.Number))),
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* {@link PropertyMeta} annotations get serialized here.
|
|
46
|
+
*/
|
|
47
|
+
meta: Schema.optional(
|
|
48
|
+
Schema.Record({
|
|
49
|
+
key: Schema.String,
|
|
50
|
+
value: Schema.Any,
|
|
51
|
+
}).pipe(Schema.mutable),
|
|
52
|
+
),
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @deprecated
|
|
56
|
+
*/
|
|
57
|
+
// TODO(dmaretskyi): We risk old schema not passing validation due to the extra fields. Remove when we are sure this is safe
|
|
58
|
+
type: Schema.optional(
|
|
59
|
+
Schema.Struct({
|
|
60
|
+
typename: Schema.String,
|
|
61
|
+
version: Schema.String,
|
|
62
|
+
|
|
63
|
+
// Not used.
|
|
64
|
+
schemaId: Schema.optional(Schema.String),
|
|
65
|
+
}).pipe(Schema.mutable),
|
|
66
|
+
),
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @deprecated Superseded by `meta`.
|
|
70
|
+
*/
|
|
71
|
+
annotations: Schema.optional(
|
|
72
|
+
Schema.Record({
|
|
73
|
+
key: Schema.String,
|
|
74
|
+
value: Schema.Any,
|
|
75
|
+
}).pipe(Schema.mutable),
|
|
76
|
+
),
|
|
77
|
+
}).pipe(Schema.mutable);
|
|
78
|
+
export type JsonSchemaEchoAnnotations = Schema.Schema.Type<typeof JsonSchemaEchoAnnotations>;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Describes a schema for the JSON-schema objects stored in ECHO.
|
|
82
|
+
* Contains extensions for ECHO (e.g., references).
|
|
83
|
+
* Ref: https://json-schema.org/draft-07/schema
|
|
84
|
+
*/
|
|
85
|
+
// TODO(burdon): Integrate with Effect Serializable?
|
|
86
|
+
// TODO(dmaretskyi): Update to latest draft: https://json-schema.org/draft/2020-12
|
|
87
|
+
const _JsonSchemaType = Schema.Struct({
|
|
88
|
+
/**
|
|
89
|
+
* Identifier for this schema.
|
|
90
|
+
* This schema might be referenced by $ref clause in other schemas.
|
|
91
|
+
*/
|
|
92
|
+
// TODO(dmaretskyi): Specify how the ids are generated.
|
|
93
|
+
// TODO(dmaretskyi): For type dxns, should this include the version?
|
|
94
|
+
$id: Schema.optional(Schema.String),
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Schema of this schema.
|
|
98
|
+
* Set to "https://json-schema.org/draft-07/schema".
|
|
99
|
+
*/
|
|
100
|
+
$schema: Schema.optional(Schema.String),
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Reference to another schema.
|
|
104
|
+
*/
|
|
105
|
+
$ref: Schema.optional(Schema.String),
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Comments are ignored when interpreting the schema.
|
|
109
|
+
*/
|
|
110
|
+
$comment: Schema.optional(Schema.String),
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Defines whether this schema is an object schema or a relation schema.
|
|
114
|
+
*/
|
|
115
|
+
entityKind: Schema.optional(EntityKindSchema),
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Typename of this schema.
|
|
119
|
+
* Only on schema representing an ECHO object.
|
|
120
|
+
*
|
|
121
|
+
* @example 'example.com/type/MyType'
|
|
122
|
+
*/
|
|
123
|
+
typename: Schema.optional(Schema.String),
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Version of this schema.
|
|
127
|
+
* Custom dialect for ECHO.
|
|
128
|
+
*/
|
|
129
|
+
version: Schema.optional(Schema.String),
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Target of this relation.
|
|
133
|
+
* Only for relation schemas.
|
|
134
|
+
* The referenced schema must be an object schema.
|
|
135
|
+
*/
|
|
136
|
+
relationTarget: Schema.optional(Schema.suspend(() => JsonSchemaType)),
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Source of this relation.
|
|
140
|
+
* Only for relation schemas.
|
|
141
|
+
* The referenced schema must be an object schema.
|
|
142
|
+
*/
|
|
143
|
+
relationSource: Schema.optional(Schema.suspend(() => JsonSchemaType)),
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Title of this schema.
|
|
147
|
+
*/
|
|
148
|
+
title: Schema.optional(Schema.String),
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Description of this schema.
|
|
152
|
+
*/
|
|
153
|
+
description: Schema.optional(Schema.String),
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Whether this schema is read-only.
|
|
157
|
+
*/
|
|
158
|
+
readOnly: Schema.optional(Schema.Boolean),
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Whether this schema is write-only.
|
|
162
|
+
*/
|
|
163
|
+
writeOnly: Schema.optional(Schema.Boolean),
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Examples of instances of this schema.
|
|
167
|
+
*/
|
|
168
|
+
examples: Schema.optional(Schema.Array(Schema.Any)),
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Default value for this schema.
|
|
172
|
+
*/
|
|
173
|
+
default: Schema.optional(Schema.Any),
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* This schema only matches values that are equal to this value.
|
|
177
|
+
*/
|
|
178
|
+
const: Schema.optional(Schema.Any),
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* This schema only matches one of the values in this array.
|
|
182
|
+
*/
|
|
183
|
+
enum: Schema.optional(Schema.Array(Schema.Any)),
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Base type of the schema.
|
|
187
|
+
*/
|
|
188
|
+
type: Schema.optional(Schema.Union(SimpleTypes, Schema.Array(SimpleTypes))),
|
|
189
|
+
|
|
190
|
+
//
|
|
191
|
+
// Numbers.
|
|
192
|
+
//
|
|
193
|
+
|
|
194
|
+
multipleOf: Schema.optional(Schema.Number.pipe(Schema.greaterThan(0))),
|
|
195
|
+
maximum: Schema.optional(Schema.Number),
|
|
196
|
+
exclusiveMaximum: Schema.optional(Schema.Number),
|
|
197
|
+
minimum: Schema.optional(Schema.Number),
|
|
198
|
+
exclusiveMinimum: Schema.optional(Schema.Number),
|
|
199
|
+
|
|
200
|
+
//
|
|
201
|
+
// Strings.
|
|
202
|
+
//
|
|
203
|
+
|
|
204
|
+
maxLength: Schema.optional(NonNegativeInteger),
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Regex pattern for strings.
|
|
208
|
+
*/
|
|
209
|
+
pattern: Schema.optional(Schema.String.pipe(FormatAnnotation.set(FormatEnum.Regex))),
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Serialized from {@link FormatAnnotationId}.
|
|
213
|
+
*/
|
|
214
|
+
format: Schema.optional(Schema.String),
|
|
215
|
+
|
|
216
|
+
//
|
|
217
|
+
// Arrays
|
|
218
|
+
//
|
|
219
|
+
|
|
220
|
+
minLength: Schema.optional(NonNegativeInteger),
|
|
221
|
+
items: Schema.optional(
|
|
222
|
+
Schema.Union(
|
|
223
|
+
Schema.suspend(() => JsonSchemaType),
|
|
224
|
+
Schema.Array(Schema.suspend(() => JsonSchemaType)),
|
|
225
|
+
),
|
|
226
|
+
),
|
|
227
|
+
additionalItems: Schema.optional(
|
|
228
|
+
Schema.Union(
|
|
229
|
+
Schema.suspend(() => JsonSchemaType),
|
|
230
|
+
Schema.Boolean,
|
|
231
|
+
),
|
|
232
|
+
),
|
|
233
|
+
maxItems: Schema.optional(NonNegativeInteger),
|
|
234
|
+
minItems: Schema.optional(NonNegativeInteger),
|
|
235
|
+
uniqueItems: Schema.optional(Schema.Boolean),
|
|
236
|
+
contains: Schema.optional(Schema.suspend(() => JsonSchemaType)),
|
|
237
|
+
|
|
238
|
+
//
|
|
239
|
+
// Objects
|
|
240
|
+
//
|
|
241
|
+
|
|
242
|
+
maxProperties: Schema.optional(NonNegativeInteger),
|
|
243
|
+
minProperties: Schema.optional(NonNegativeInteger),
|
|
244
|
+
required: Schema.optional(StringArray),
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Non-standard JSON Schema extension.
|
|
248
|
+
* Defines the order of properties in the object.
|
|
249
|
+
* The unmentioned properties are placed at the end.
|
|
250
|
+
*
|
|
251
|
+
* Related: https://github.com/json-schema/json-schema/issues/119
|
|
252
|
+
*/
|
|
253
|
+
propertyOrder: Schema.optional(StringArray),
|
|
254
|
+
|
|
255
|
+
additionalProperties: Schema.optional(JsonSchemaOrBoolean),
|
|
256
|
+
properties: Schema.optional(
|
|
257
|
+
Schema.Record({
|
|
258
|
+
key: Schema.String,
|
|
259
|
+
value: Schema.suspend(() => JsonSchemaType),
|
|
260
|
+
}).pipe(Schema.mutable),
|
|
261
|
+
),
|
|
262
|
+
patternProperties: Schema.optional(
|
|
263
|
+
Schema.Record({
|
|
264
|
+
key: Schema.String,
|
|
265
|
+
value: Schema.suspend(() => JsonSchemaType),
|
|
266
|
+
}).pipe(Schema.mutable),
|
|
267
|
+
),
|
|
268
|
+
propertyNames: Schema.optional(Schema.suspend(() => JsonSchemaType)),
|
|
269
|
+
|
|
270
|
+
definitions: Schema.optional(
|
|
271
|
+
Schema.mutable(
|
|
272
|
+
Schema.Record({
|
|
273
|
+
key: Schema.String,
|
|
274
|
+
value: Schema.suspend(() => JsonSchemaType),
|
|
275
|
+
}),
|
|
276
|
+
),
|
|
277
|
+
),
|
|
278
|
+
dependencies: Schema.optional(
|
|
279
|
+
Schema.Record({
|
|
280
|
+
key: Schema.String,
|
|
281
|
+
value: Schema.suspend(() => Schema.Union(Schema.String, StringArray, JsonSchemaType)).annotations({
|
|
282
|
+
identifier: 'dependency',
|
|
283
|
+
description: 'Dependency',
|
|
284
|
+
}),
|
|
285
|
+
}),
|
|
286
|
+
),
|
|
287
|
+
|
|
288
|
+
contentMediaType: Schema.optional(Schema.String),
|
|
289
|
+
contentEncoding: Schema.optional(Schema.String),
|
|
290
|
+
|
|
291
|
+
if: Schema.optional(Schema.suspend(() => JsonSchemaType)),
|
|
292
|
+
then: Schema.optional(Schema.suspend(() => JsonSchemaType)),
|
|
293
|
+
else: Schema.optional(Schema.suspend(() => JsonSchemaType)),
|
|
294
|
+
allOf: Schema.optional(Schema.Array(Schema.suspend(() => JsonSchemaType))),
|
|
295
|
+
anyOf: Schema.optional(Schema.Array(Schema.suspend(() => JsonSchemaType))),
|
|
296
|
+
oneOf: Schema.optional(Schema.Array(Schema.suspend(() => JsonSchemaType))),
|
|
297
|
+
not: Schema.optional(Schema.suspend(() => JsonSchemaType)),
|
|
298
|
+
$defs: Schema.optional(
|
|
299
|
+
Schema.mutable(
|
|
300
|
+
Schema.Record({
|
|
301
|
+
key: Schema.String,
|
|
302
|
+
value: Schema.suspend(() => JsonSchemaType),
|
|
303
|
+
}),
|
|
304
|
+
),
|
|
305
|
+
),
|
|
306
|
+
|
|
307
|
+
//
|
|
308
|
+
// ECHO extensions.
|
|
309
|
+
//
|
|
310
|
+
|
|
311
|
+
currency: Schema.optional(Schema.String),
|
|
312
|
+
|
|
313
|
+
reference: Schema.optional(
|
|
314
|
+
Schema.mutable(
|
|
315
|
+
Schema.Struct({
|
|
316
|
+
schema: Schema.suspend(() => JsonSchemaType),
|
|
317
|
+
schemaVersion: Schema.optional(Schema.String),
|
|
318
|
+
schemaObject: Schema.optional(Schema.String),
|
|
319
|
+
}),
|
|
320
|
+
),
|
|
321
|
+
),
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* ECHO-specific annotations.
|
|
325
|
+
*/
|
|
326
|
+
// TODO(dmaretskyi): Since we are adding a lot of new extensions to the JSON Schema, it is safer to namespace them here.
|
|
327
|
+
annotations: Schema.optional(Schema.mutable(JsonSchemaEchoAnnotations)),
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* @deprecated Use `annotations` instead.
|
|
331
|
+
*/
|
|
332
|
+
echo: Schema.optional(Schema.mutable(JsonSchemaEchoAnnotations)),
|
|
333
|
+
}).annotations({ identifier: 'jsonSchema', description: 'JSON Schema' });
|
|
334
|
+
|
|
335
|
+
export const JsonSchemaFields = Object.keys(_JsonSchemaType.fields);
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* https://json-schema.org/draft-07/schema
|
|
339
|
+
*/
|
|
340
|
+
export interface JsonSchemaType extends Schema.Schema.Type<Schema.mutable<typeof _JsonSchemaType>> {}
|
|
341
|
+
|
|
342
|
+
export const JsonSchemaType: Schema.Schema<JsonSchemaType> = _JsonSchemaType.pipe(Schema.mutable);
|
|
343
|
+
|
|
344
|
+
// TODO(burdon): Factor out JSON schema utils.
|
|
345
|
+
|
|
346
|
+
export const getSchemaProperty = (schema: JsonSchemaType, property: JsonProp): JsonSchemaType | undefined => {
|
|
347
|
+
return schema.properties?.[property];
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
// TODO(burdon): Properties should be ordered.
|
|
351
|
+
export const setSchemaProperty = (schema: JsonSchemaType, property: JsonProp, value: JsonSchemaType) => {
|
|
352
|
+
schema.properties ??= {};
|
|
353
|
+
schema.properties[property] = value;
|
|
354
|
+
return schema;
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* @internal
|
|
359
|
+
*/
|
|
360
|
+
export const ECHO_ANNOTATIONS_NS_DEPRECATED_KEY: keyof JsonSchemaType = 'echo';
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* @internal
|
|
364
|
+
*/
|
|
365
|
+
export const ECHO_ANNOTATIONS_NS_KEY = 'annotations';
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* @internal
|
|
369
|
+
* @returns ECHO annotations namespace object in its normalized form.
|
|
370
|
+
*
|
|
371
|
+
* `meta` holds PropertyMeta annotations.
|
|
372
|
+
* `annotations` holds other annotations.
|
|
373
|
+
*/
|
|
374
|
+
export const getNormalizedEchoAnnotations = (obj: JsonSchemaType): JsonSchemaEchoAnnotations | undefined => {
|
|
375
|
+
if (obj[ECHO_ANNOTATIONS_NS_KEY] != null && obj[ECHO_ANNOTATIONS_NS_DEPRECATED_KEY] != null) {
|
|
376
|
+
return normalizeEchoAnnotations({
|
|
377
|
+
...obj[ECHO_ANNOTATIONS_NS_DEPRECATED_KEY],
|
|
378
|
+
...obj[ECHO_ANNOTATIONS_NS_KEY],
|
|
379
|
+
});
|
|
380
|
+
} else if (obj[ECHO_ANNOTATIONS_NS_KEY] != null) {
|
|
381
|
+
return normalizeEchoAnnotations(obj[ECHO_ANNOTATIONS_NS_KEY]!);
|
|
382
|
+
} else if (obj[ECHO_ANNOTATIONS_NS_DEPRECATED_KEY] != null) {
|
|
383
|
+
return normalizeEchoAnnotations(obj[ECHO_ANNOTATIONS_NS_DEPRECATED_KEY]!);
|
|
384
|
+
} else {
|
|
385
|
+
return undefined;
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
const normalizeEchoAnnotations = (obj: JsonSchemaEchoAnnotations): JsonSchemaEchoAnnotations => {
|
|
390
|
+
if (!obj.annotations) {
|
|
391
|
+
return obj;
|
|
392
|
+
} else {
|
|
393
|
+
const res = {
|
|
394
|
+
...obj,
|
|
395
|
+
meta: {
|
|
396
|
+
...obj.annotations,
|
|
397
|
+
...(obj.meta ?? {}),
|
|
398
|
+
},
|
|
399
|
+
};
|
|
400
|
+
delete res.annotations;
|
|
401
|
+
return res;
|
|
402
|
+
}
|
|
403
|
+
};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Option from 'effect/Option';
|
|
6
|
+
import * as Schema from 'effect/Schema';
|
|
7
|
+
|
|
8
|
+
import { type JsonPath, getField } from '@dxos/effect';
|
|
9
|
+
import { assertArgument, invariant } from '@dxos/invariant';
|
|
10
|
+
import { DXN, ObjectId } from '@dxos/keys';
|
|
11
|
+
import { assumeType } from '@dxos/util';
|
|
12
|
+
|
|
13
|
+
import { DescriptionAnnotation, LabelAnnotation } from '../ast';
|
|
14
|
+
|
|
15
|
+
import { type InternalObjectProps, SchemaId, SelfDXNId } from './model';
|
|
16
|
+
|
|
17
|
+
//
|
|
18
|
+
// Accessors based on model.
|
|
19
|
+
//
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Returns a DXN for an object or schema.
|
|
23
|
+
* @deprecated Use `Obj.getDXN`.
|
|
24
|
+
*/
|
|
25
|
+
export const getObjectDXN = (object: any): DXN | undefined => {
|
|
26
|
+
invariant(!Schema.isSchema(object), 'schema not allowed in this function');
|
|
27
|
+
assertArgument(typeof object === 'object' && object != null, 'object', 'expected object');
|
|
28
|
+
assumeType<InternalObjectProps>(object);
|
|
29
|
+
|
|
30
|
+
if (object[SelfDXNId]) {
|
|
31
|
+
invariant(object[SelfDXNId] instanceof DXN, 'Invalid object model: invalid self dxn');
|
|
32
|
+
return object[SelfDXNId];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!ObjectId.isValid(object.id)) {
|
|
36
|
+
throw new TypeError('Object id is not valid.');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return DXN.fromLocalObjectId(object.id);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Returns the schema for the given object if one is defined.
|
|
44
|
+
*/
|
|
45
|
+
// TODO(burdon): Reconcile with `getTypename`.
|
|
46
|
+
// TODO(dmaretskyi): For echo objects, this always returns the root schema.
|
|
47
|
+
export const getSchema = (obj: unknown | undefined): Schema.Schema.AnyNoContext | undefined => {
|
|
48
|
+
if (obj) {
|
|
49
|
+
return (obj as any)[SchemaId];
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Internal use only.
|
|
55
|
+
*/
|
|
56
|
+
export const setSchema = (obj: any, schema: Schema.Schema.AnyNoContext) => {
|
|
57
|
+
Object.defineProperty(obj, SchemaId, {
|
|
58
|
+
value: schema,
|
|
59
|
+
writable: false,
|
|
60
|
+
enumerable: false,
|
|
61
|
+
configurable: false,
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @deprecated Use {@link Obj.getLabel} instead.
|
|
67
|
+
* Returns the label for a given object based on {@link LabelAnnotationId}.
|
|
68
|
+
*/
|
|
69
|
+
export const getLabelForObject = (obj: unknown | undefined): string | undefined => {
|
|
70
|
+
const schema = getSchema(obj);
|
|
71
|
+
if (schema) {
|
|
72
|
+
return getLabel(schema, obj);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Returns the label for a given object based on {@link LabelAnnotationId}.
|
|
78
|
+
*/
|
|
79
|
+
// TODO(burdon): Convert to JsonPath?
|
|
80
|
+
export const getLabel = <S extends Schema.Schema.Any>(schema: S, object: Schema.Schema.Type<S>): string | undefined => {
|
|
81
|
+
const annotation = LabelAnnotation.get(schema).pipe(Option.getOrElse(() => ['name']));
|
|
82
|
+
for (const accessor of annotation) {
|
|
83
|
+
assertArgument(
|
|
84
|
+
typeof accessor === 'string',
|
|
85
|
+
'accessor',
|
|
86
|
+
'Label annotation must be a string or an array of strings',
|
|
87
|
+
);
|
|
88
|
+
const value = getField(object, accessor as JsonPath);
|
|
89
|
+
switch (typeof value) {
|
|
90
|
+
case 'string':
|
|
91
|
+
case 'number':
|
|
92
|
+
case 'boolean':
|
|
93
|
+
case 'bigint':
|
|
94
|
+
case 'symbol':
|
|
95
|
+
return value.toString();
|
|
96
|
+
case 'undefined':
|
|
97
|
+
case 'object':
|
|
98
|
+
case 'function':
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return undefined;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Sets the label for a given object based on {@link LabelAnnotationId}.
|
|
108
|
+
*/
|
|
109
|
+
export const setLabel = <S extends Schema.Schema.Any>(schema: S, object: Schema.Schema.Type<S>, label: string) => {
|
|
110
|
+
const annotation = LabelAnnotation.get(schema).pipe(
|
|
111
|
+
Option.map((field) => field[0]),
|
|
112
|
+
Option.getOrElse(() => 'name'),
|
|
113
|
+
);
|
|
114
|
+
object[annotation] = label;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Returns the label for a given object based on {@link LabelAnnotationId}.
|
|
119
|
+
*/
|
|
120
|
+
// TODO(burdon): Convert to JsonPath?
|
|
121
|
+
export const getDescription = <S extends Schema.Schema.Any>(
|
|
122
|
+
schema: S,
|
|
123
|
+
object: Schema.Schema.Type<S>,
|
|
124
|
+
): string | undefined => {
|
|
125
|
+
const accessor = DescriptionAnnotation.get(schema).pipe(Option.getOrElse(() => 'description'));
|
|
126
|
+
assertArgument(typeof accessor === 'string', 'accessor', 'Description annotation must be a string');
|
|
127
|
+
const value = getField(object, accessor as JsonPath);
|
|
128
|
+
switch (typeof value) {
|
|
129
|
+
case 'string':
|
|
130
|
+
case 'number':
|
|
131
|
+
case 'boolean':
|
|
132
|
+
case 'bigint':
|
|
133
|
+
case 'symbol':
|
|
134
|
+
return value.toString();
|
|
135
|
+
case 'undefined':
|
|
136
|
+
case 'object':
|
|
137
|
+
case 'function':
|
|
138
|
+
default:
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Sets the description for a given object based on {@link DescriptionAnnotationId}.
|
|
145
|
+
*/
|
|
146
|
+
export const setDescription = <S extends Schema.Schema.Any>(
|
|
147
|
+
schema: S,
|
|
148
|
+
object: Schema.Schema.Type<S>,
|
|
149
|
+
description: string,
|
|
150
|
+
) => {
|
|
151
|
+
const accessor = DescriptionAnnotation.get(schema).pipe(Option.getOrElse(() => 'description'));
|
|
152
|
+
object[accessor] = description;
|
|
153
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Schema from 'effect/Schema';
|
|
6
|
+
|
|
7
|
+
import { type BaseObject } from '../types';
|
|
8
|
+
|
|
9
|
+
import { getTypename } from './typename';
|
|
10
|
+
|
|
11
|
+
// TODO(dmaretskyi): Rename to represent commonality between objects and relations (e.g. `entity`).
|
|
12
|
+
export type TypedObjectOptions = {
|
|
13
|
+
// TODO(burdon): Document.
|
|
14
|
+
partial?: true;
|
|
15
|
+
// TODO(burdon): Document.
|
|
16
|
+
record?: true;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
// TODO(burdon): Comment required.
|
|
23
|
+
// TODO(dmaretskyi): Rename to represent commonality between objects and relations (e.g. `entity`).
|
|
24
|
+
type SimplifiedSchemaFields<
|
|
25
|
+
SchemaFields extends Schema.Struct.Fields,
|
|
26
|
+
Options extends TypedObjectOptions,
|
|
27
|
+
> = Options['partial'] extends boolean
|
|
28
|
+
? Schema.SimplifyMutable<Partial<Schema.Struct.Type<SchemaFields>>>
|
|
29
|
+
: Schema.SimplifyMutable<Schema.Struct.Type<SchemaFields>>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
*/
|
|
34
|
+
// TODO(burdon): Comment required.
|
|
35
|
+
// TODO(dmaretskyi): Rename to represent commonality between objects and relations (e.g. `entity`).
|
|
36
|
+
export type TypedObjectFields<
|
|
37
|
+
SchemaFields extends Schema.Struct.Fields,
|
|
38
|
+
Options extends TypedObjectOptions,
|
|
39
|
+
> = SimplifiedSchemaFields<SchemaFields, Options> & { id: string } & (Options['record'] extends boolean
|
|
40
|
+
? Schema.SimplifyMutable<Schema.IndexSignature.Type<Schema.IndexSignature.Records>>
|
|
41
|
+
: {});
|
|
42
|
+
|
|
43
|
+
export const makeTypedEntityClass = (
|
|
44
|
+
typename: string,
|
|
45
|
+
version: string,
|
|
46
|
+
baseSchema: Schema.Schema.AnyNoContext,
|
|
47
|
+
): Schema.SchemaClass<any> => {
|
|
48
|
+
return class {
|
|
49
|
+
// Implement TypedObject properties.
|
|
50
|
+
static readonly typename = typename;
|
|
51
|
+
static readonly version = version;
|
|
52
|
+
|
|
53
|
+
// Implement Schema.Schema properties.
|
|
54
|
+
// TODO(burdon): Comment required.
|
|
55
|
+
static readonly [Schema.TypeId] = schemaVariance;
|
|
56
|
+
static readonly ast = baseSchema.ast;
|
|
57
|
+
static readonly annotations = baseSchema.annotations.bind(baseSchema);
|
|
58
|
+
static readonly pipe = baseSchema.pipe.bind(baseSchema);
|
|
59
|
+
|
|
60
|
+
// TODO(burdon): Comment required.
|
|
61
|
+
static [Symbol.hasInstance](obj: BaseObject) {
|
|
62
|
+
return obj != null && getTypename(obj) === typename;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// TODO(burdon): Throw APIError.
|
|
66
|
+
private constructor() {
|
|
67
|
+
throw new Error('Use live(Typename, { ...fields }) to instantiate an object.');
|
|
68
|
+
}
|
|
69
|
+
} as any;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const schemaVariance = {
|
|
73
|
+
_A: (_: any) => _,
|
|
74
|
+
_I: (_: any) => _,
|
|
75
|
+
_R: (_: never) => _,
|
|
76
|
+
};
|