@dxos/echo 0.8.1 → 0.8.2-main.10c050d
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 +116 -0
- package/dist/lib/browser/index.mjs +241 -32
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +243 -28
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +241 -32
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/Obj.d.ts +39 -0
- package/dist/types/src/Obj.d.ts.map +1 -0
- package/dist/types/src/Ref.d.ts +11 -0
- package/dist/types/src/Ref.d.ts.map +1 -0
- package/dist/types/src/Relation.d.ts +19 -0
- package/dist/types/src/Relation.d.ts.map +1 -0
- package/dist/types/src/Type.d.ts +80 -42
- package/dist/types/src/Type.d.ts.map +1 -1
- package/dist/types/src/{Database.d.ts → experimental/database.d.ts} +1 -1
- package/dist/types/src/experimental/database.d.ts.map +1 -0
- package/dist/types/src/experimental/index.d.ts +1 -0
- package/dist/types/src/experimental/index.d.ts.map +1 -0
- package/dist/types/src/{Queue.d.ts → experimental/queue.d.ts} +1 -1
- package/dist/types/src/experimental/queue.d.ts.map +1 -0
- package/dist/types/src/{Space.d.ts → experimental/space.d.ts} +1 -1
- package/dist/types/src/experimental/space.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +5 -5
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/{api.test.d.ts.map → test/api.test.d.ts.map} +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +14 -15
- package/src/Obj.ts +86 -0
- package/src/Ref.ts +21 -0
- package/src/Relation.ts +45 -0
- package/src/Type.ts +103 -75
- package/src/{Database.ts → experimental/database.ts} +1 -1
- package/src/experimental/index.ts +7 -0
- package/src/{Queue.ts → experimental/queue.ts} +1 -1
- package/src/index.ts +6 -7
- package/src/test/api.test.ts +128 -0
- package/dist/types/src/Database.d.ts.map +0 -1
- package/dist/types/src/Queue.d.ts.map +0 -1
- package/dist/types/src/Space.d.ts.map +0 -1
- package/src/api.test.ts +0 -94
- /package/dist/types/src/{api.test.d.ts → test/api.test.d.ts} +0 -0
- /package/src/{Space.ts → experimental/space.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../../../src/experimental/queue.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,yBAAiB,KAAK,CAAC,GAAE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"space.d.ts","sourceRoot":"","sources":["../../../../src/experimental/space.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,WAAW,KAAK,CAAC,GAAE"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { DXN } from '@dxos/keys';
|
|
2
|
-
export { DXN };
|
|
3
|
-
export * as Database from './Database';
|
|
4
|
-
export * as Queue from './Queue';
|
|
5
|
-
export * as Space from './Space';
|
|
6
1
|
export * as Type from './Type';
|
|
2
|
+
export * as Obj from './Obj';
|
|
3
|
+
export * as Relation from './Relation';
|
|
4
|
+
export * as Ref from './Ref';
|
|
5
|
+
export { type Live } from '@dxos/live-object';
|
|
6
|
+
export { Filter, Query } from '@dxos/echo-schema';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC;AAC/B,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC;AAC7B,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC;AAE7B,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.test.d.ts","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"api.test.d.ts","sourceRoot":"","sources":["../../../../src/test/api.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"5.
|
|
1
|
+
{"version":"5.8.3"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/echo",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2-main.10c050d",
|
|
4
4
|
"description": "ECHO API",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -21,20 +21,19 @@
|
|
|
21
21
|
"src"
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@preact/signals-core": "^1.
|
|
25
|
-
"effect": "3.
|
|
26
|
-
"@dxos/debug": "0.8.
|
|
27
|
-
"@dxos/echo-
|
|
28
|
-
"@dxos/echo-
|
|
29
|
-
"@dxos/
|
|
30
|
-
"@dxos/
|
|
31
|
-
"@dxos/echo-schema": "0.8.
|
|
32
|
-
"@dxos/
|
|
33
|
-
"@dxos/
|
|
34
|
-
"@dxos/
|
|
35
|
-
"@dxos/
|
|
36
|
-
"@dxos/
|
|
37
|
-
"@dxos/util": "0.8.1"
|
|
24
|
+
"@preact/signals-core": "^1.9.0",
|
|
25
|
+
"effect": "3.14.21",
|
|
26
|
+
"@dxos/debug": "0.8.2-main.10c050d",
|
|
27
|
+
"@dxos/echo-protocol": "0.8.2-main.10c050d",
|
|
28
|
+
"@dxos/echo-signals": "0.8.2-main.10c050d",
|
|
29
|
+
"@dxos/invariant": "0.8.2-main.10c050d",
|
|
30
|
+
"@dxos/effect": "0.8.2-main.10c050d",
|
|
31
|
+
"@dxos/echo-schema": "0.8.2-main.10c050d",
|
|
32
|
+
"@dxos/live-object": "0.8.2-main.10c050d",
|
|
33
|
+
"@dxos/log": "0.8.2-main.10c050d",
|
|
34
|
+
"@dxos/keys": "0.8.2-main.10c050d",
|
|
35
|
+
"@dxos/util": "0.8.2-main.10c050d",
|
|
36
|
+
"@dxos/node-std": "0.8.2-main.10c050d"
|
|
38
37
|
},
|
|
39
38
|
"publishConfig": {
|
|
40
39
|
"access": "public"
|
package/src/Obj.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Schema } from 'effect';
|
|
6
|
+
|
|
7
|
+
import * as EchoSchema from '@dxos/echo-schema';
|
|
8
|
+
import { assertArgument, invariant } from '@dxos/invariant';
|
|
9
|
+
import type { DXN } from '@dxos/keys';
|
|
10
|
+
import * as LiveObject from '@dxos/live-object';
|
|
11
|
+
|
|
12
|
+
import type * as Type from './Type';
|
|
13
|
+
|
|
14
|
+
export type Any = EchoSchema.AnyEchoObject;
|
|
15
|
+
|
|
16
|
+
export const make = LiveObject.live;
|
|
17
|
+
|
|
18
|
+
// TODO(dmaretskyi): Currently broken
|
|
19
|
+
export const isObject = (obj: unknown): obj is Any => {
|
|
20
|
+
return LiveObject.isLiveObject(obj);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Check that object or relation is an instance of a schema.
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* const person = Obj.make(Person, { name: 'John' });
|
|
28
|
+
* const isPerson = Obj.instanceOf(Person);
|
|
29
|
+
* isPerson(person); // true
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export const instanceOf: {
|
|
33
|
+
<S extends Type.Relation.Any | Type.Obj.Any>(schema: S): (value: unknown) => value is S;
|
|
34
|
+
<S extends Type.Relation.Any | Type.Obj.Any>(schema: S, value: unknown): value is S;
|
|
35
|
+
} = ((...args: any[]) => {
|
|
36
|
+
if (args.length === 1) {
|
|
37
|
+
return (obj: unknown) => EchoSchema.isInstanceOf(args[0], obj);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return EchoSchema.isInstanceOf(args[0], args[1]);
|
|
41
|
+
}) as any;
|
|
42
|
+
|
|
43
|
+
export const getSchema = EchoSchema.getSchema;
|
|
44
|
+
|
|
45
|
+
export const getDXN = (obj: Any): DXN => {
|
|
46
|
+
assertArgument(!Schema.isSchema(obj), 'Object should not be a schema.');
|
|
47
|
+
const dxn = EchoSchema.getDXN(obj);
|
|
48
|
+
invariant(dxn != null, 'Invalid object.');
|
|
49
|
+
return dxn;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @returns The DXN of the object's type.
|
|
54
|
+
* @example dxn:example.com/type/Contact:1.0.0
|
|
55
|
+
*/
|
|
56
|
+
export const getSchemaDXN = (obj: Any): DXN => {
|
|
57
|
+
const type = EchoSchema.getType(obj);
|
|
58
|
+
invariant(type != null, 'Invalid object.');
|
|
59
|
+
return type;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @returns The typename of the object's type.
|
|
64
|
+
* @example `example.com/type/Contact`
|
|
65
|
+
*/
|
|
66
|
+
export const getTypename = (obj: Any): string | undefined => {
|
|
67
|
+
const schema = getSchema(obj);
|
|
68
|
+
if (schema == null) {
|
|
69
|
+
// Try to extract typename from DXN.
|
|
70
|
+
return getSchemaDXN(obj)?.asTypeDXN()?.type;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return EchoSchema.getTypename(schema);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const getMeta = (obj: Any): EchoSchema.ObjectMeta => {
|
|
77
|
+
const meta = EchoSchema.getMeta(obj);
|
|
78
|
+
invariant(meta != null, 'Invalid object.');
|
|
79
|
+
return meta;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const isDeleted = (obj: Any): boolean => {
|
|
83
|
+
const deleted = EchoSchema.isDeleted(obj);
|
|
84
|
+
invariant(typeof deleted === 'boolean', 'Invalid object.');
|
|
85
|
+
return deleted;
|
|
86
|
+
};
|
package/src/Ref.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as EchoSchema from '@dxos/echo-schema';
|
|
6
|
+
|
|
7
|
+
import type * as Obj from './Obj';
|
|
8
|
+
|
|
9
|
+
export type Any = EchoSchema.Ref<Obj.Any>;
|
|
10
|
+
|
|
11
|
+
export const make = EchoSchema.Ref.make;
|
|
12
|
+
|
|
13
|
+
export const isRef: (value: unknown) => value is Any = EchoSchema.Ref.isRef;
|
|
14
|
+
|
|
15
|
+
// TODO(dmaretskyi): Consider just allowing `make` to accept DXN.
|
|
16
|
+
export const fromDXN = EchoSchema.Ref.fromDXN;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Extract reference target.
|
|
20
|
+
*/
|
|
21
|
+
export type Target<R extends Any> = R extends EchoSchema.Ref<infer T> ? T : never;
|
package/src/Relation.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as EchoSchema from '@dxos/echo-schema';
|
|
6
|
+
import { invariant } from '@dxos/invariant';
|
|
7
|
+
import * as LiveObject from '@dxos/live-object';
|
|
8
|
+
|
|
9
|
+
export type Any = EchoSchema.AnyEchoObject & EchoSchema.RelationSourceTargetRefs;
|
|
10
|
+
|
|
11
|
+
export const make = LiveObject.live;
|
|
12
|
+
|
|
13
|
+
export const isRelation = (value: unknown): value is Any => {
|
|
14
|
+
if (typeof value !== 'object' || value === null) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
if (EchoSchema.ATTR_RELATION_SOURCE in value || EchoSchema.ATTR_RELATION_TARGET in value) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const kind = (value as any)[EchoSchema.EntityKindPropertyId];
|
|
22
|
+
return kind === EchoSchema.EntityKind.Relation;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @returns Relation source.
|
|
27
|
+
* @throws If the object is not a relation.
|
|
28
|
+
*/
|
|
29
|
+
export const getSource = <T extends Any>(relation: T): EchoSchema.RelationSource<T> => {
|
|
30
|
+
invariant(isRelation(relation));
|
|
31
|
+
const obj = relation[EchoSchema.RelationSourceId];
|
|
32
|
+
invariant(obj !== undefined, `Invalid source: ${relation.id}`);
|
|
33
|
+
return obj;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @returns Relation target.
|
|
38
|
+
* @throws If the object is not a relation.
|
|
39
|
+
*/
|
|
40
|
+
export const getTarget = <T extends Any>(relation: T): EchoSchema.RelationTarget<T> => {
|
|
41
|
+
invariant(isRelation(relation));
|
|
42
|
+
const obj = relation[EchoSchema.RelationTargetId];
|
|
43
|
+
invariant(obj !== undefined, `Invalid target: ${relation.id}`);
|
|
44
|
+
return obj;
|
|
45
|
+
};
|
package/src/Type.ts
CHANGED
|
@@ -4,96 +4,124 @@
|
|
|
4
4
|
|
|
5
5
|
import { type Schema } from 'effect';
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
type ImmutableSchema,
|
|
12
|
-
type JsonSchemaType,
|
|
13
|
-
type TypeMeta,
|
|
14
|
-
EchoObject,
|
|
15
|
-
EntityKind,
|
|
16
|
-
ObjectId,
|
|
17
|
-
Ref as Ref$,
|
|
18
|
-
getTypeAnnotation,
|
|
19
|
-
getSchema,
|
|
20
|
-
getSchemaDXN,
|
|
21
|
-
getSchemaTypename,
|
|
22
|
-
getSchemaVersion,
|
|
23
|
-
isInstanceOf,
|
|
24
|
-
} from '@dxos/echo-schema';
|
|
25
|
-
import { create as create$, makeRef } from '@dxos/live-object';
|
|
7
|
+
import type { EncodedReference } from '@dxos/echo-protocol';
|
|
8
|
+
import * as EchoSchema from '@dxos/echo-schema';
|
|
9
|
+
import { invariant } from '@dxos/invariant';
|
|
10
|
+
import type * as Keys from '@dxos/keys';
|
|
26
11
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// - Use `declare namespace` for types (no code is generated). See Effect pattern, where Schema is a namespace, interface, and function.
|
|
32
|
-
// - Test with @dxos/schema/testing types.
|
|
33
|
-
// - Define user (Composer) types in namespace (e.g., of plugin) and drop Type suffix; remove all deprecated Braneframe types.
|
|
12
|
+
/**
|
|
13
|
+
* ECHO schema.
|
|
14
|
+
*/
|
|
15
|
+
export type Schema = EchoSchema.EchoSchema;
|
|
34
16
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
isInstanceOf as instanceOf,
|
|
45
|
-
};
|
|
17
|
+
/**
|
|
18
|
+
* EchoObject schema.
|
|
19
|
+
*/
|
|
20
|
+
export const Obj = EchoSchema.EchoObject;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* EchoRelation schema.
|
|
24
|
+
*/
|
|
25
|
+
export const Relation = EchoSchema.EchoRelation;
|
|
46
26
|
|
|
47
27
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* @category api namespace
|
|
51
|
-
* @since 0.9.0
|
|
28
|
+
* Ref schema.
|
|
52
29
|
*/
|
|
53
|
-
export
|
|
30
|
+
export const Ref: <S extends Obj.Any>(schema: S) => EchoSchema.Ref$<Schema.Schema.Type<S>> = EchoSchema.Ref;
|
|
31
|
+
|
|
32
|
+
export namespace Obj {
|
|
33
|
+
/**
|
|
34
|
+
* Type that represents an arbitrary schema type of an object.
|
|
35
|
+
* NOTE: This is not an instance type.
|
|
36
|
+
*/
|
|
37
|
+
// TODO(dmaretskyi): If schema was covariant, we could specify props in here, like `id: ObjectId`.
|
|
38
|
+
export type Any = Schema.Schema.AnyNoContext;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export namespace Relation {
|
|
42
|
+
/**
|
|
43
|
+
* Type that represents an arbitrary schema type of a relation.
|
|
44
|
+
* NOTE: This is not an instance type.
|
|
45
|
+
*/
|
|
46
|
+
// TODO(dmaretskyi): If schema was covariant, we could specify props in here, like `id: ObjectId`.
|
|
47
|
+
export type Any = Schema.Schema.AnyNoContext;
|
|
48
|
+
|
|
54
49
|
/**
|
|
55
|
-
*
|
|
50
|
+
* Get relation target type.
|
|
56
51
|
*/
|
|
57
|
-
export type
|
|
52
|
+
export type Target<A> = A extends EchoSchema.RelationSourceTargetRefs<infer T, infer _S> ? T : never;
|
|
58
53
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Get relation source type.
|
|
56
|
+
*/
|
|
57
|
+
export type Source<A> = A extends EchoSchema.RelationSourceTargetRefs<infer _T, infer S> ? S : never;
|
|
62
58
|
}
|
|
63
59
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
export namespace Ref {
|
|
61
|
+
/**
|
|
62
|
+
* Type that represents an arbitrary schema type of a reference.
|
|
63
|
+
* NOTE: This is not an instance type.
|
|
64
|
+
*/
|
|
65
|
+
export type Any = Schema.Schema<EchoSchema.Ref<any>, EncodedReference>;
|
|
66
|
+
}
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Gets the full DXN of the schema.
|
|
70
|
+
* Will include the version if it's a `type` DXN.
|
|
71
|
+
* @example "dxn:example.com/type/Person:0.1.0"
|
|
72
|
+
* @example "dxn:echo:SSSSSSSSSS:XXXXXXXXXXXXX"
|
|
73
|
+
*/
|
|
74
|
+
export const getDXN = (schema: Obj.Any | Relation.Any): Keys.DXN | undefined => {
|
|
75
|
+
return EchoSchema.getSchemaDXN(schema);
|
|
76
|
+
};
|
|
70
77
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
78
|
+
/**
|
|
79
|
+
* @param schema - Schema to get the typename from.
|
|
80
|
+
* @returns The typename of the schema. Example: `example.com/type/Person`.
|
|
81
|
+
*/
|
|
82
|
+
export const getTypename = (schema: Obj.Any | Relation.Any): string => {
|
|
83
|
+
const typename = EchoSchema.getSchemaTypename(schema);
|
|
84
|
+
invariant(typeof typename === 'string' && !typename.startsWith('dxn:'), 'Invalid typename');
|
|
85
|
+
return typename;
|
|
86
|
+
};
|
|
74
87
|
|
|
75
88
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* @example
|
|
79
|
-
* ```ts
|
|
80
|
-
* const Org = S.Struct({
|
|
81
|
-
* name: S.String,
|
|
82
|
-
* }).pipe(Type.def({ typename: 'example.com/type/Org', version: '1.0.0' }));
|
|
83
|
-
* ```
|
|
89
|
+
* Gets the version of the schema.
|
|
90
|
+
* @example 0.1.0
|
|
84
91
|
*/
|
|
85
|
-
export const
|
|
92
|
+
export const getVersion = (schema: Obj.Any | Relation.Any): string => {
|
|
93
|
+
const version = EchoSchema.getSchemaVersion(schema);
|
|
94
|
+
invariant(typeof version === 'string' && version.match(/^\d+\.\d+\.\d+$/), 'Invalid version');
|
|
95
|
+
return version;
|
|
96
|
+
};
|
|
86
97
|
|
|
87
98
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* ```ts
|
|
92
|
-
* import { Type } from '@dxos/echo';
|
|
93
|
-
* const Contact = S.Struct({
|
|
94
|
-
* name: S.String,
|
|
95
|
-
* employer: Type.Ref(Org),
|
|
96
|
-
* }).pipe(Type.def({ typename: 'example.com/type/Contact', version: '1.0.0' }));
|
|
97
|
-
* ```
|
|
99
|
+
* ECHO type metadata.
|
|
98
100
|
*/
|
|
99
|
-
export
|
|
101
|
+
export type Meta = EchoSchema.TypeAnnotation;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Gets the meta data of the schema.
|
|
105
|
+
*/
|
|
106
|
+
export const getMeta = (schema: Obj.Any | Relation.Any): Meta | undefined => {
|
|
107
|
+
return EchoSchema.getTypeAnnotation(schema);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export { EntityKind as Kind } from '@dxos/echo-schema';
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @returns True if the schema is mutable.
|
|
114
|
+
*/
|
|
115
|
+
export const isMutable = (schema: Obj.Any | Relation.Any): boolean => {
|
|
116
|
+
return EchoSchema.isMutable(schema);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export { SpaceId, ObjectId, DXN } from '@dxos/keys';
|
|
120
|
+
|
|
121
|
+
export {
|
|
122
|
+
//
|
|
123
|
+
Expando,
|
|
124
|
+
JsonSchemaType as JsonSchema,
|
|
125
|
+
toJsonSchema,
|
|
126
|
+
Format,
|
|
127
|
+
} from '@dxos/echo-schema';
|
package/src/index.ts
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { DXN } from '@dxos/keys';
|
|
6
|
-
|
|
7
|
-
export { DXN };
|
|
8
|
-
|
|
9
|
-
export * as Database from './Database';
|
|
10
|
-
export * as Queue from './Queue';
|
|
11
|
-
export * as Space from './Space';
|
|
12
5
|
export * as Type from './Type';
|
|
6
|
+
export * as Obj from './Obj';
|
|
7
|
+
export * as Relation from './Relation';
|
|
8
|
+
export * as Ref from './Ref';
|
|
9
|
+
|
|
10
|
+
export { type Live } from '@dxos/live-object';
|
|
11
|
+
export { Filter, Query } from '@dxos/echo-schema';
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Schema } from 'effect';
|
|
6
|
+
import { describe, test } from 'vitest';
|
|
7
|
+
|
|
8
|
+
import { raise } from '@dxos/debug';
|
|
9
|
+
import { FormatEnum, FormatAnnotation } from '@dxos/echo-schema';
|
|
10
|
+
|
|
11
|
+
import { Obj, Ref, Type, type Live } from '../index';
|
|
12
|
+
|
|
13
|
+
namespace Testing {
|
|
14
|
+
export const Organization = Schema.Struct({
|
|
15
|
+
id: Type.ObjectId,
|
|
16
|
+
name: Schema.String,
|
|
17
|
+
}).pipe(
|
|
18
|
+
Type.Obj({
|
|
19
|
+
typename: 'example.com/type/Organization',
|
|
20
|
+
version: '0.1.0',
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export interface Organization extends Schema.Schema.Type<typeof Organization> {}
|
|
25
|
+
|
|
26
|
+
export const Person = Schema.Struct({
|
|
27
|
+
name: Schema.String,
|
|
28
|
+
dob: Schema.optional(Schema.String),
|
|
29
|
+
email: Schema.optional(Schema.String.pipe(FormatAnnotation.set(FormatEnum.Email))),
|
|
30
|
+
organization: Schema.optional(Type.Ref(Organization)),
|
|
31
|
+
}).pipe(
|
|
32
|
+
Type.Obj({
|
|
33
|
+
typename: 'example.com/type/Person',
|
|
34
|
+
version: '0.1.0',
|
|
35
|
+
}),
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
export interface Person extends Schema.Schema.Type<typeof Person> {}
|
|
39
|
+
|
|
40
|
+
// export const WorksFor = S.Struct({
|
|
41
|
+
// id: Type.ObjectId,
|
|
42
|
+
// since: S.String,
|
|
43
|
+
// jobTitle: S.String,
|
|
44
|
+
// ...Range({ from, to }),
|
|
45
|
+
// ...Provenance({ source: 'duckduckgo.com', confidence: 0.9 }), // keys
|
|
46
|
+
// ...Relation.make({ source: Contact, target: Organization }),
|
|
47
|
+
// }).pipe(
|
|
48
|
+
// Type.Relation({
|
|
49
|
+
// typename: 'example.com/relation/WorksFor',
|
|
50
|
+
// version: '0.1.0',
|
|
51
|
+
// }),
|
|
52
|
+
// );
|
|
53
|
+
|
|
54
|
+
// {
|
|
55
|
+
// const contact = db.add(create(Contact, { name: 'Test' }));
|
|
56
|
+
// const organization = db.add(create(Organization, { name: 'DXOS' }));
|
|
57
|
+
// db.add(create(WorksFor, { source: contact, target: organization }));
|
|
58
|
+
// }
|
|
59
|
+
|
|
60
|
+
export const WorksFor = Schema.Struct({
|
|
61
|
+
// id: Type.ObjectId,
|
|
62
|
+
role: Schema.String,
|
|
63
|
+
}).pipe(
|
|
64
|
+
// Type.Relation
|
|
65
|
+
Type.Obj({
|
|
66
|
+
typename: 'example.com/type/WorksFor',
|
|
67
|
+
version: '0.1.0',
|
|
68
|
+
// source: Person,
|
|
69
|
+
// target: Organization,
|
|
70
|
+
}),
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
export interface WorksFor extends Schema.Schema.Type<typeof WorksFor> {}
|
|
74
|
+
|
|
75
|
+
// TODO(burdon): Fix (Type.Obj currently removes TypeLiteral that implements the `make` function).
|
|
76
|
+
// Property 'make' does not exist on type 'EchoObjectSchema<Struct<{ timestamp: PropertySignature<":", string, never, ":", string, true, never>; }>>'.ts(2339)
|
|
77
|
+
export const MessageStruct = Schema.Struct({
|
|
78
|
+
// TODO(burdon): Support S.Date; Custom Timestamp (with defaults).
|
|
79
|
+
// TODO(burdon): Support defaults (update create and create).
|
|
80
|
+
timestamp: Schema.String.pipe(
|
|
81
|
+
Schema.propertySignature,
|
|
82
|
+
Schema.withConstructorDefault(() => new Date().toISOString()),
|
|
83
|
+
),
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
export const Message = MessageStruct.pipe(
|
|
87
|
+
Type.Obj({
|
|
88
|
+
typename: 'example.com/type/Message',
|
|
89
|
+
version: '0.1.0',
|
|
90
|
+
}),
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
export interface Message extends Schema.Schema.Type<typeof Message> {}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
describe('Experimental API review', () => {
|
|
97
|
+
test('type checks', ({ expect }) => {
|
|
98
|
+
const contact = Obj.make(Testing.Person, { name: 'Test' });
|
|
99
|
+
const type: Schema.Schema<Testing.Person> = Obj.getSchema(contact) ?? raise(new Error('No schema found'));
|
|
100
|
+
|
|
101
|
+
expect(Type.getDXN(type)?.typename).to.eq(Testing.Person.typename);
|
|
102
|
+
expect(Type.getTypename(type)).to.eq('example.com/type/Person');
|
|
103
|
+
expect(Type.getVersion(type)).to.eq('0.1.0');
|
|
104
|
+
expect(Type.getMeta(type)).to.deep.eq({
|
|
105
|
+
kind: Type.Kind.Object,
|
|
106
|
+
typename: 'example.com/type/Person',
|
|
107
|
+
version: '0.1.0',
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test('instance checks', ({ expect }) => {
|
|
112
|
+
const organization: Live<Testing.Organization> = Obj.make(Testing.Organization, { name: 'DXOS' });
|
|
113
|
+
const contact: Live<Testing.Person> = Obj.make(Testing.Person, {
|
|
114
|
+
name: 'Test',
|
|
115
|
+
organization: Ref.make(organization),
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
expect(Schema.is(Testing.Person)(contact)).to.be.true;
|
|
119
|
+
expect(Testing.Person.instanceOf(contact)).to.be.true;
|
|
120
|
+
expect(Obj.instanceOf(Testing.Person)(contact)).to.be.true;
|
|
121
|
+
expect(Obj.instanceOf(Testing.Organization)(organization)).to.be.true;
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('default props', ({ expect }) => {
|
|
125
|
+
const message = Obj.make(Testing.Message, Testing.MessageStruct.make({}));
|
|
126
|
+
expect(message.timestamp).to.exist;
|
|
127
|
+
});
|
|
128
|
+
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Database.d.ts","sourceRoot":"","sources":["../../../src/Database.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,WAAW,QAAQ,CAAC,GAAE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Queue.d.ts","sourceRoot":"","sources":["../../../src/Queue.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,WAAW,KAAK,CAAC,GAAE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Space.d.ts","sourceRoot":"","sources":["../../../src/Space.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,WAAW,KAAK,CAAC,GAAE"}
|