@dxos/echo 0.8.3-main.7f5a14c → 0.8.3-staging.0fa589b

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.
Files changed (53) hide show
  1. package/dist/lib/browser/chunk-UYPR62ZB.mjs +624 -0
  2. package/dist/lib/browser/chunk-UYPR62ZB.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +10 -282
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +70 -0
  7. package/dist/lib/browser/testing/index.mjs.map +7 -0
  8. package/dist/lib/node/chunk-4HQE2F3L.cjs +644 -0
  9. package/dist/lib/node/chunk-4HQE2F3L.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +9 -282
  11. package/dist/lib/node/index.cjs.map +4 -4
  12. package/dist/lib/node/meta.json +1 -1
  13. package/dist/lib/node/testing/index.cjs +89 -0
  14. package/dist/lib/node/testing/index.cjs.map +7 -0
  15. package/dist/lib/node-esm/chunk-BYBICDIO.mjs +624 -0
  16. package/dist/lib/node-esm/chunk-BYBICDIO.mjs.map +7 -0
  17. package/dist/lib/node-esm/index.mjs +10 -282
  18. package/dist/lib/node-esm/index.mjs.map +4 -4
  19. package/dist/lib/node-esm/meta.json +1 -1
  20. package/dist/lib/node-esm/testing/index.mjs +70 -0
  21. package/dist/lib/node-esm/testing/index.mjs.map +7 -0
  22. package/dist/types/src/Obj.d.ts +23 -8
  23. package/dist/types/src/Obj.d.ts.map +1 -1
  24. package/dist/types/src/Ref.d.ts +1 -1
  25. package/dist/types/src/Ref.d.ts.map +1 -1
  26. package/dist/types/src/Relation.d.ts +36 -10
  27. package/dist/types/src/Relation.d.ts.map +1 -1
  28. package/dist/types/src/Type.d.ts +78 -15
  29. package/dist/types/src/Type.d.ts.map +1 -1
  30. package/dist/types/src/index.d.ts +1 -1
  31. package/dist/types/src/index.d.ts.map +1 -1
  32. package/dist/types/src/query/dsl.d.ts +218 -0
  33. package/dist/types/src/query/dsl.d.ts.map +1 -0
  34. package/dist/types/src/query/dsl.test.d.ts +2 -0
  35. package/dist/types/src/query/dsl.test.d.ts.map +1 -0
  36. package/dist/types/src/query/index.d.ts +2 -0
  37. package/dist/types/src/query/index.d.ts.map +1 -0
  38. package/dist/types/src/testing/index.d.ts +2 -0
  39. package/dist/types/src/testing/index.d.ts.map +1 -0
  40. package/dist/types/src/testing/types.d.ts +113 -0
  41. package/dist/types/src/testing/types.d.ts.map +1 -0
  42. package/package.json +56 -12
  43. package/src/Obj.ts +44 -6
  44. package/src/Ref.ts +1 -1
  45. package/src/Relation.ts +75 -13
  46. package/src/Type.ts +113 -14
  47. package/src/index.ts +1 -1
  48. package/src/query/dsl.test.ts +323 -0
  49. package/src/query/dsl.ts +646 -0
  50. package/src/query/index.ts +5 -0
  51. package/src/test/api.test.ts +37 -7
  52. package/src/testing/index.ts +5 -0
  53. package/src/testing/types.ts +91 -0
@@ -0,0 +1,113 @@
1
+ import { Schema } from 'effect';
2
+ import { Type } from '..';
3
+ export declare namespace Testing {
4
+ const _Contact: Type.obj<Schema.SchemaClass<{
5
+ readonly name?: string | undefined;
6
+ readonly email?: string | undefined;
7
+ readonly username?: string | undefined;
8
+ readonly tasks?: import("@dxos/echo-schema").Ref<Task>[] | undefined;
9
+ readonly address?: {
10
+ readonly city?: string | undefined;
11
+ readonly state?: string | undefined;
12
+ readonly zip?: string | undefined;
13
+ readonly coordinates: {
14
+ readonly lat?: number | undefined;
15
+ readonly lng?: number | undefined;
16
+ };
17
+ } | undefined;
18
+ }, {
19
+ readonly name?: string | undefined;
20
+ readonly email?: string | undefined;
21
+ readonly username?: string | undefined;
22
+ readonly tasks?: import("@dxos/echo-protocol").EncodedReference[] | undefined;
23
+ readonly address?: {
24
+ readonly coordinates: {
25
+ readonly lat?: number | undefined;
26
+ readonly lng?: number | undefined;
27
+ };
28
+ readonly city?: string | undefined;
29
+ readonly state?: string | undefined;
30
+ readonly zip?: string | undefined;
31
+ } | undefined;
32
+ }, never>>;
33
+ export interface Contact extends Schema.Schema.Type<typeof _Contact> {
34
+ }
35
+ export const Contact: Schema.Schema<Contact, Schema.Schema.Encoded<typeof _Contact>, never>;
36
+ const _Task: Type.obj<Schema.SchemaClass<{
37
+ readonly description?: string | undefined;
38
+ readonly title?: string | undefined;
39
+ readonly assignee?: import("@dxos/echo-schema").Ref<Contact> | undefined;
40
+ readonly completed?: boolean | undefined;
41
+ readonly previous?: import("@dxos/echo-schema").Ref<Task> | undefined;
42
+ readonly subTasks?: import("@dxos/echo-schema").Ref<Task>[] | undefined;
43
+ }, {
44
+ readonly description?: string | undefined;
45
+ readonly title?: string | undefined;
46
+ readonly assignee?: import("@dxos/echo-protocol").EncodedReference | undefined;
47
+ readonly completed?: boolean | undefined;
48
+ readonly previous?: import("@dxos/echo-protocol").EncodedReference | undefined;
49
+ readonly subTasks?: import("@dxos/echo-protocol").EncodedReference[] | undefined;
50
+ }, never>>;
51
+ export interface Task extends Schema.Schema.Type<typeof _Task> {
52
+ }
53
+ export const Task: Schema.Schema<Task, Schema.Schema.Encoded<typeof _Task>, never>;
54
+ export enum RecordType {
55
+ UNDEFINED = 0,
56
+ PERSONAL = 1,
57
+ WORK = 2
58
+ }
59
+ export const Container: Type.obj<Schema.SchemaClass<{
60
+ readonly records?: {
61
+ readonly type?: RecordType | undefined;
62
+ readonly description?: string | undefined;
63
+ readonly title?: string | undefined;
64
+ readonly contacts?: import("@dxos/echo-schema").Ref<Contact>[] | undefined;
65
+ }[] | undefined;
66
+ readonly objects?: import("@dxos/echo-schema").Ref<Type.Expando>[] | undefined;
67
+ }, {
68
+ readonly records?: {
69
+ readonly type?: RecordType | undefined;
70
+ readonly description?: string | undefined;
71
+ readonly title?: string | undefined;
72
+ readonly contacts?: import("@dxos/echo-protocol").EncodedReference[] | undefined;
73
+ }[] | undefined;
74
+ readonly objects?: import("@dxos/echo-protocol").EncodedReference[] | undefined;
75
+ }, never>>;
76
+ export const WorksFor: Type.relation<Schema.Struct<{
77
+ since: Schema.optional<typeof Schema.String>;
78
+ }>, Schema.Schema<Contact, {
79
+ id: string;
80
+ name?: string | undefined;
81
+ email?: string | undefined;
82
+ username?: string | undefined;
83
+ tasks?: import("@dxos/echo-protocol").EncodedReference[] | undefined;
84
+ address?: {
85
+ readonly coordinates: {
86
+ readonly lat?: number | undefined;
87
+ readonly lng?: number | undefined;
88
+ };
89
+ readonly city?: string | undefined;
90
+ readonly state?: string | undefined;
91
+ readonly zip?: string | undefined;
92
+ } | undefined;
93
+ }, never>, Schema.Schema<Contact, {
94
+ id: string;
95
+ name?: string | undefined;
96
+ email?: string | undefined;
97
+ username?: string | undefined;
98
+ tasks?: import("@dxos/echo-protocol").EncodedReference[] | undefined;
99
+ address?: {
100
+ readonly coordinates: {
101
+ readonly lat?: number | undefined;
102
+ readonly lng?: number | undefined;
103
+ };
104
+ readonly city?: string | undefined;
105
+ readonly state?: string | undefined;
106
+ readonly zip?: string | undefined;
107
+ } | undefined;
108
+ }, never>>;
109
+ export interface WorksFor extends Schema.Schema.Type<typeof WorksFor> {
110
+ }
111
+ export {};
112
+ }
113
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/testing/types.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAG1B,yBAAiB,OAAO,CAAC;IACvB,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAoBb,CAAC;IACF,MAAM,WAAW,OAAQ,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,QAAQ,CAAC;KAAG;IACvE,MAAM,CAAC,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,QAAQ,CAAC,EAAE,KAAK,CAAY,CAAC;IAEvG,MAAM,KAAK;;;;;;;;;;;;;;cAaV,CAAC;IACF,MAAM,WAAW,IAAK,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC;KAAG;IACjE,MAAM,CAAC,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,KAAK,CAAC,EAAE,KAAK,CAAS,CAAC;IAE3F,MAAM,MAAM,UAAU;QACpB,SAAS,IAAI;QACb,QAAQ,IAAI;QACZ,IAAI,IAAI;KACT;IAED,MAAM,CAAC,MAAM,SAAS;;;;;;;;;;;;;;;;cAoBrB,CAAC;IAEF,MAAM,CAAC,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cASpB,CAAC;IACF,MAAM,WAAW,QAAS,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,QAAQ,CAAC;KAAG;;CACzE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/echo",
3
- "version": "0.8.3-main.7f5a14c",
3
+ "version": "0.8.3-staging.0fa589b",
4
4
  "description": "ECHO API",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -13,9 +13,53 @@
13
13
  "types": "./dist/types/src/index.d.ts",
14
14
  "browser": "./dist/lib/browser/index.mjs",
15
15
  "node": "./dist/lib/node-esm/index.mjs"
16
+ },
17
+ "./Type": {
18
+ "types": "./dist/types/src/Type.d.ts",
19
+ "browser": "./dist/lib/browser/Type.mjs",
20
+ "node": "./dist/lib/node-esm/Type.mjs"
21
+ },
22
+ "./Obj": {
23
+ "types": "./dist/types/src/Obj.d.ts",
24
+ "browser": "./dist/lib/browser/Obj.mjs",
25
+ "node": "./dist/lib/node-esm/Obj.mjs"
26
+ },
27
+ "./Relation": {
28
+ "types": "./dist/types/src/Relation.d.ts",
29
+ "browser": "./dist/lib/browser/Relation.mjs",
30
+ "node": "./dist/lib/node-esm/Relation.mjs"
31
+ },
32
+ "./Ref": {
33
+ "types": "./dist/types/src/Ref.d.ts",
34
+ "browser": "./dist/lib/browser/Ref.mjs",
35
+ "node": "./dist/lib/node-esm/Ref.mjs"
36
+ },
37
+ "./testing": {
38
+ "types": "./dist/types/src/testing/types.d.ts",
39
+ "browser": "./dist/lib/browser/testing/index.mjs",
40
+ "node": "./dist/lib/node-esm/testing/index.mjs"
16
41
  }
17
42
  },
18
43
  "types": "dist/types/src/index.d.ts",
44
+ "typesVersions": {
45
+ "*": {
46
+ "Type": [
47
+ "dist/types/src/Type.d.ts"
48
+ ],
49
+ "Obj": [
50
+ "dist/types/src/Obj.d.ts"
51
+ ],
52
+ "Relation": [
53
+ "dist/types/src/Relation.d.ts"
54
+ ],
55
+ "Ref": [
56
+ "dist/types/src/Ref.d.ts"
57
+ ],
58
+ "testing": [
59
+ "dist/types/src/testing/index.d.ts"
60
+ ]
61
+ }
62
+ },
19
63
  "files": [
20
64
  "dist",
21
65
  "src"
@@ -23,17 +67,17 @@
23
67
  "dependencies": {
24
68
  "@preact/signals-core": "^1.9.0",
25
69
  "effect": "3.14.21",
26
- "@dxos/debug": "0.8.3-main.7f5a14c",
27
- "@dxos/echo-protocol": "0.8.3-main.7f5a14c",
28
- "@dxos/echo-schema": "0.8.3-main.7f5a14c",
29
- "@dxos/echo-signals": "0.8.3-main.7f5a14c",
30
- "@dxos/effect": "0.8.3-main.7f5a14c",
31
- "@dxos/keys": "0.8.3-main.7f5a14c",
32
- "@dxos/invariant": "0.8.3-main.7f5a14c",
33
- "@dxos/live-object": "0.8.3-main.7f5a14c",
34
- "@dxos/log": "0.8.3-main.7f5a14c",
35
- "@dxos/node-std": "0.8.3-main.7f5a14c",
36
- "@dxos/util": "0.8.3-main.7f5a14c"
70
+ "@dxos/debug": "0.8.3-staging.0fa589b",
71
+ "@dxos/echo-protocol": "0.8.3-staging.0fa589b",
72
+ "@dxos/echo-schema": "0.8.3-staging.0fa589b",
73
+ "@dxos/effect": "0.8.3-staging.0fa589b",
74
+ "@dxos/echo-signals": "0.8.3-staging.0fa589b",
75
+ "@dxos/invariant": "0.8.3-staging.0fa589b",
76
+ "@dxos/keys": "0.8.3-staging.0fa589b",
77
+ "@dxos/live-object": "0.8.3-staging.0fa589b",
78
+ "@dxos/log": "0.8.3-staging.0fa589b",
79
+ "@dxos/node-std": "0.8.3-staging.0fa589b",
80
+ "@dxos/util": "0.8.3-staging.0fa589b"
37
81
  },
38
82
  "publishConfig": {
39
83
  "access": "public"
package/src/Obj.ts CHANGED
@@ -7,16 +7,54 @@ import { Schema } from 'effect';
7
7
  import * as EchoSchema from '@dxos/echo-schema';
8
8
  import { assertArgument, invariant } from '@dxos/invariant';
9
9
  import { type DXN } from '@dxos/keys';
10
- import * as LiveObject from '@dxos/live-object';
10
+ import type * as LiveObject from '@dxos/live-object';
11
+ import { live } from '@dxos/live-object';
11
12
  import { assumeType } from '@dxos/util';
12
13
 
13
14
  import type * as Ref from './Ref';
15
+ import type * as Relation from './Relation';
14
16
  import type * as Type from './Type';
15
17
 
16
- export type Obj<T = any> = EchoSchema.AnyEchoObject & T;
17
- export type Any = EchoSchema.AnyEchoObject;
18
+ // NOTE: Don't export: Obj.Any and Obj.Obj form the public API.
19
+ interface ObjBase extends Type.OfKind<EchoSchema.EntityKind.Object> {
20
+ readonly id: EchoSchema.ObjectId;
21
+ }
18
22
 
19
- export const make = LiveObject.live;
23
+ /**
24
+ * Object type with specific properties.
25
+ */
26
+ export type Obj<Props> = ObjBase & Props;
27
+
28
+ /**
29
+ * Base type for all ECHO objects.
30
+ */
31
+ export interface Any extends ObjBase {}
32
+
33
+ type MakeProps<T> = {
34
+ id?: EchoSchema.ObjectId;
35
+ } & Type.Properties<T>;
36
+
37
+ /**
38
+ * Creates new object.
39
+ */
40
+ // TODO(dmaretskyi): Move meta into props.
41
+ export const make = <S extends Type.Obj.Any>(
42
+ schema: S,
43
+ props: NoInfer<MakeProps<Schema.Schema.Type<S>>>,
44
+ meta?: EchoSchema.ObjectMeta,
45
+ ): LiveObject.Live<Schema.Schema.Type<S>> => {
46
+ assertArgument(
47
+ EchoSchema.getTypeAnnotation(schema)?.kind === EchoSchema.EntityKind.Object,
48
+ 'Expected an object schema',
49
+ );
50
+
51
+ if (props[EchoSchema.MetaId] != null) {
52
+ meta = props[EchoSchema.MetaId] as any;
53
+ delete props[EchoSchema.MetaId];
54
+ }
55
+
56
+ return live<Schema.Schema.Type<S>>(schema, props as any, meta);
57
+ };
20
58
 
21
59
  export const isObject = (obj: unknown): obj is Any => {
22
60
  assumeType<EchoSchema.InternalObjectProps>(obj);
@@ -111,7 +149,7 @@ export type JSON = EchoSchema.ObjectJSON;
111
149
  *
112
150
  * The same algorithm is used when calling the standard `JSON.stringify(obj)` function.
113
151
  */
114
- export const toJSON = (obj: Any): JSON => EchoSchema.objectToJSON(obj);
152
+ export const toJSON = (obj: Any | Relation.Any): JSON => EchoSchema.objectToJSON(obj);
115
153
 
116
154
  /**
117
155
  * Creates an object from its json representation, performing schema validation.
@@ -120,4 +158,4 @@ export const toJSON = (obj: Any): JSON => EchoSchema.objectToJSON(obj);
120
158
  * The function need to be async to support resolving the schema as well as the relation endpoints.
121
159
  */
122
160
  export const fromJSON: (json: unknown, options?: { refResolver?: Ref.Resolver }) => Promise<Any> =
123
- EchoSchema.objectFromJSON;
161
+ EchoSchema.objectFromJSON as any;
package/src/Ref.ts CHANGED
@@ -6,7 +6,7 @@ import * as EchoSchema from '@dxos/echo-schema';
6
6
 
7
7
  import type * as Obj from './Obj';
8
8
 
9
- export type Ref<T extends Obj.Any> = EchoSchema.Ref<T>;
9
+ export type Ref<T> = EchoSchema.Ref<T>;
10
10
  export type Any = EchoSchema.Ref<Obj.Any>;
11
11
 
12
12
  export const Array = EchoSchema.RefArray;
package/src/Relation.ts CHANGED
@@ -2,18 +2,78 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import { type Schema } from 'effect';
6
+
7
+ import { raise } from '@dxos/debug';
5
8
  import * as EchoSchema from '@dxos/echo-schema';
6
9
  import { assertArgument, invariant } from '@dxos/invariant';
7
10
  import { DXN } from '@dxos/keys';
8
- import * as LiveObject from '@dxos/live-object';
11
+ import { type Live, live } from '@dxos/live-object';
9
12
  import { assumeType } from '@dxos/util';
10
13
 
11
- export type Any = EchoSchema.AnyEchoObject & EchoSchema.RelationSourceTargetRefs;
14
+ import type * as Obj from './Obj';
15
+ import type * as Type from './Type';
16
+
17
+ // NOTE: Don't export: Relation.Relation and Relation.Any form the public API.
18
+ interface RelationBase<Source, Target>
19
+ extends Type.Relation.Endpoints<Source, Target>,
20
+ Type.OfKind<EchoSchema.EntityKind.Relation> {
21
+ readonly id: EchoSchema.ObjectId;
22
+ }
23
+
24
+ /**
25
+ * Relation type with specific properties.
26
+ */
27
+ export type Relation<Source extends Obj.Any, Target extends Obj.Any, Props> = RelationBase<Source, Target> & Props;
28
+
29
+ /**
30
+ * Base type for all ECHO relations.
31
+ */
32
+ export interface Any extends RelationBase<Obj.Any, Obj.Any> {}
33
+
34
+ // TODO(dmaretskyi): Has to be `unique symbol`.
35
+ export const Source: unique symbol = EchoSchema.RelationSourceId as any;
36
+ export type Source = typeof Source;
37
+ export const Target: unique symbol = EchoSchema.RelationTargetId as any;
38
+ export type Target = typeof Target;
39
+
40
+ type MakeProps<T extends Any> = {
41
+ id?: EchoSchema.ObjectId;
42
+ [Source]: T[Source];
43
+ [Target]: T[Target];
44
+ } & Type.Properties<T>;
45
+
46
+ /**
47
+ * Creates new relation.
48
+ * @param schema - Relation schema.
49
+ * @param props - Relation properties. Endpoints are passed as [Relation.Source] and [Relation.Target] keys.
50
+ * @param meta - Relation metadata.
51
+ * @returns
52
+ */
53
+ // NOTE: Writing the definition this way (with generic over schema) makes typescript perfer to infer the type from the first param (this schema) rather than the second param (the props).
54
+ // TODO(dmaretskyi): Move meta into props.
55
+ export const make = <S extends Type.Relation.Any>(
56
+ schema: S,
57
+ props: NoInfer<MakeProps<Schema.Schema.Type<S>>>,
58
+ meta?: EchoSchema.ObjectMeta,
59
+ ): Live<Schema.Schema.Type<S> & Type.OfKind<EchoSchema.EntityKind.Relation>> => {
60
+ assertArgument(
61
+ EchoSchema.getTypeAnnotation(schema)?.kind === EchoSchema.EntityKind.Relation,
62
+ 'Expected a relation schema',
63
+ );
64
+
65
+ if (props[EchoSchema.MetaId] != null) {
66
+ meta = props[EchoSchema.MetaId] as any;
67
+ delete props[EchoSchema.MetaId];
68
+ }
12
69
 
13
- export const Source = EchoSchema.RelationSourceId;
14
- export const Target = EchoSchema.RelationTargetId;
70
+ const sourceDXN = EchoSchema.getObjectDXN(props[Source]) ?? raise(new Error('Unresolved relation source'));
71
+ const targetDXN = EchoSchema.getObjectDXN(props[Target]) ?? raise(new Error('Unresolved relation target'));
72
+ (props as any)[EchoSchema.RelationSourceDXNId] = sourceDXN;
73
+ (props as any)[EchoSchema.RelationTargetDXNId] = targetDXN;
15
74
 
16
- export const make = LiveObject.live;
75
+ return live<Schema.Schema.Type<S>>(schema, props as any, meta);
76
+ };
17
77
 
18
78
  export const isRelation = (value: unknown): value is Any => {
19
79
  if (typeof value !== 'object' || value === null) {
@@ -34,7 +94,7 @@ export const isRelation = (value: unknown): value is Any => {
34
94
  export const getSourceDXN = (value: Any): DXN => {
35
95
  assertArgument(isRelation(value), 'Expected a relation');
36
96
  assumeType<EchoSchema.InternalObjectProps>(value);
37
- const dxn = value[EchoSchema.RelationSourceDXNId];
97
+ const dxn = (value as EchoSchema.InternalObjectProps)[EchoSchema.RelationSourceDXNId];
38
98
  invariant(dxn instanceof DXN);
39
99
  return dxn;
40
100
  };
@@ -46,7 +106,7 @@ export const getSourceDXN = (value: Any): DXN => {
46
106
  export const getTargetDXN = (value: Any): DXN => {
47
107
  assertArgument(isRelation(value), 'Expected a relation');
48
108
  assumeType<EchoSchema.InternalObjectProps>(value);
49
- const dxn = value[EchoSchema.RelationTargetDXNId];
109
+ const dxn = (value as EchoSchema.InternalObjectProps)[EchoSchema.RelationTargetDXNId];
50
110
  invariant(dxn instanceof DXN);
51
111
  return dxn;
52
112
  };
@@ -55,20 +115,22 @@ export const getTargetDXN = (value: Any): DXN => {
55
115
  * @returns Relation source.
56
116
  * @throws If the object is not a relation.
57
117
  */
58
- export const getSource = <T extends Any>(relation: T): EchoSchema.RelationSource<T> => {
118
+ export const getSource = <T extends Any>(relation: T): Type.Relation.Source<T> => {
59
119
  assertArgument(isRelation(relation), 'Expected a relation');
60
- const obj = relation[EchoSchema.RelationSourceId];
120
+ assumeType<EchoSchema.InternalObjectProps>(relation);
121
+ const obj = (relation as EchoSchema.InternalObjectProps)[EchoSchema.RelationSourceId];
61
122
  invariant(obj !== undefined, `Invalid source: ${relation.id}`);
62
- return obj;
123
+ return obj as Type.Relation.Source<T>;
63
124
  };
64
125
 
65
126
  /**
66
127
  * @returns Relation target.
67
128
  * @throws If the object is not a relation.
68
129
  */
69
- export const getTarget = <T extends Any>(relation: T): EchoSchema.RelationTarget<T> => {
130
+ export const getTarget = <T extends Any>(relation: T): Type.Relation.Target<T> => {
70
131
  assertArgument(isRelation(relation), 'Expected a relation');
71
- const obj = relation[EchoSchema.RelationTargetId];
132
+ assumeType<EchoSchema.InternalObjectProps>(relation);
133
+ const obj = (relation as EchoSchema.InternalObjectProps)[EchoSchema.RelationTargetId];
72
134
  invariant(obj !== undefined, `Invalid target: ${relation.id}`);
73
- return obj;
135
+ return obj as Type.Relation.Target<T>;
74
136
  };
package/src/Type.ts CHANGED
@@ -3,23 +3,75 @@
3
3
  //
4
4
 
5
5
  import { type Schema } from 'effect';
6
+ import type { Simplify } from 'effect/Schema';
6
7
 
7
8
  import type { EncodedReference } from '@dxos/echo-protocol';
8
9
  import * as EchoSchema from '@dxos/echo-schema';
10
+ import type { ToMutable } from '@dxos/echo-schema';
9
11
  import { invariant } from '@dxos/invariant';
10
12
  import type * as Keys from '@dxos/keys';
11
13
 
14
+ import type * as RelationModule from './Relation';
15
+
16
+ export const KindId: unique symbol = EchoSchema.EntityKindId as any;
17
+ export type KindId = typeof KindId;
18
+
19
+ export { EntityKind as Kind } from '@dxos/echo-schema';
20
+
21
+ /**
22
+ * Assigns a kind to an Object or Relation instance.
23
+ */
24
+ // NOTE: Needed to make `isRelation` and `isObject` checks work.
25
+ export interface OfKind<Kind extends EchoSchema.EntityKind> {
26
+ readonly id: Keys.ObjectId;
27
+ readonly [KindId]: Kind;
28
+ }
29
+
30
+ interface ObjJsonProps {
31
+ id: string;
32
+ }
33
+
34
+ interface RelationJsonProps {
35
+ id: string;
36
+ [EchoSchema.ATTR_RELATION_SOURCE]: string;
37
+ [EchoSchema.ATTR_RELATION_TARGET]: string;
38
+ }
39
+
12
40
  /**
13
- * ECHO schema.
41
+ * Returns all properties of an object or relation except for the id and kind.
42
+ */
43
+ export type Properties<T> = Omit<T, 'id' | KindId | RelationModule.Source | RelationModule.Target>;
44
+
45
+ /**
46
+ * Base ECHO schema type.
14
47
  */
15
48
  export type Schema = EchoSchema.EchoSchema;
16
49
 
17
50
  /**
18
- * EchoObject schema.
51
+ * Return type of the `Obj` schema constructor.
52
+ *
53
+ * This typedef avoids `TS4023` error (name from external module cannot be used named).
54
+ * See Effect's note on interface types.
55
+ */
56
+ export interface obj<Self extends Schema.Schema.Any>
57
+ extends Schema.AnnotableClass<
58
+ obj<Self>,
59
+ OfKind<EchoSchema.EntityKind.Object> & ToMutable<Schema.Schema.Type<Self>>,
60
+ Simplify<ObjJsonProps & ToMutable<Schema.Schema.Encoded<Self>>>,
61
+ Schema.Schema.Context<Self>
62
+ >,
63
+ EchoSchema.TypeMeta {}
64
+
65
+ /**
66
+ * Object schema.
19
67
  */
20
- export const Obj = EchoSchema.EchoObject;
68
+ export const Obj: {
69
+ (opts: EchoSchema.TypeMeta): <Self extends Schema.Schema.Any>(self: Self) => obj<Self>;
70
+ } = EchoSchema.EchoObject as any;
21
71
 
22
- // TODO(buurdon): Move to Obj?
72
+ /**
73
+ * Object schema type definitions.
74
+ */
23
75
  export namespace Obj {
24
76
  /**
25
77
  * Type that represents an arbitrary schema type of an object.
@@ -30,11 +82,38 @@ export namespace Obj {
30
82
  }
31
83
 
32
84
  /**
33
- * EchoRelation schema.
85
+ * Return type of the `Relation` schema constructor.
86
+ *
87
+ * This typedef avoids `TS4023` error (name from external module cannot be used named).
88
+ * See Effect's note on interface types.
89
+ */
90
+ export interface relation<
91
+ Self extends Schema.Schema.Any,
92
+ SourceSchema extends Schema.Schema.Any,
93
+ TargetSchema extends Schema.Schema.Any,
94
+ > extends Schema.AnnotableClass<
95
+ relation<Self, SourceSchema, TargetSchema>,
96
+ OfKind<EchoSchema.EntityKind.Relation> &
97
+ Relation.Endpoints<Schema.Schema.Type<SourceSchema>, Schema.Schema.Type<TargetSchema>> &
98
+ ToMutable<Schema.Schema.Type<Self>>,
99
+ Simplify<RelationJsonProps & ToMutable<Schema.Schema.Encoded<Self>>>,
100
+ Schema.Schema.Context<Self>
101
+ >,
102
+ EchoSchema.TypeMeta {}
103
+
104
+ /**
105
+ * Relation schema.
34
106
  */
35
- export const Relation = EchoSchema.EchoRelation;
107
+ // TODO(dmaretskyi): I have to redefine the type here so that the definition uses symbols from @dxos/echo/Relation.
108
+ export const Relation: {
109
+ <Source extends Schema.Schema.AnyNoContext, Target extends Schema.Schema.AnyNoContext>(
110
+ opts: EchoSchema.EchoRelationOptions<Source, Target>,
111
+ ): <Self extends Schema.Schema.Any>(self: Self) => relation<Self, Source, Target>;
112
+ } = EchoSchema.EchoRelation as any;
36
113
 
37
- // TODO(buurdon): Move to Relation?
114
+ /**
115
+ * Relation schema type definitions.
116
+ */
38
117
  export namespace Relation {
39
118
  /**
40
119
  * Type that represents an arbitrary schema type of a relation.
@@ -46,18 +125,32 @@ export namespace Relation {
46
125
  /**
47
126
  * Get relation target type.
48
127
  */
49
- export type Target<A> = A extends EchoSchema.RelationSourceTargetRefs<infer T, infer _S> ? T : never;
128
+ export type Target<A> = A extends Relation.Endpoints<infer _S, infer T> ? T : never;
50
129
 
51
130
  /**
52
131
  * Get relation source type.
53
132
  */
54
- export type Source<A> = A extends EchoSchema.RelationSourceTargetRefs<infer _T, infer S> ? S : never;
133
+ export type Source<A> = A extends Relation.Endpoints<infer S, infer _T> ? S : never;
134
+
135
+ export type Endpoints<Source, Target> = {
136
+ [RelationModule.Source]: Source;
137
+ [RelationModule.Target]: Target;
138
+ };
55
139
  }
56
140
 
141
+ /**
142
+ * Return type of the `Ref` schema constructor.
143
+ *
144
+ * This typedef avoids `TS4023` error (name from external module cannot be used named).
145
+ * See Effect's note on interface types.
146
+ */
147
+ export interface ref<TargetSchema extends Schema.Schema.Any>
148
+ extends EchoSchema.Ref$<Schema.Schema.Type<TargetSchema>> {}
149
+
57
150
  /**
58
151
  * Ref schema.
59
152
  */
60
- export const Ref: <S extends Obj.Any>(schema: S) => EchoSchema.Ref$<Schema.Schema.Type<S>> = EchoSchema.Ref;
153
+ export const Ref: <S extends Obj.Any>(schema: S) => ref<S> = EchoSchema.Ref;
61
154
 
62
155
  export interface Ref<T> extends Schema.SchemaClass<EchoSchema.Ref<T>, EncodedReference> {}
63
156
 
@@ -112,8 +205,6 @@ export const getMeta = (schema: Obj.Any | Relation.Any): Meta | undefined => {
112
205
  return EchoSchema.getTypeAnnotation(schema);
113
206
  };
114
207
 
115
- export { EntityKind as Kind } from '@dxos/echo-schema';
116
-
117
208
  /**
118
209
  * @returns True if the schema is mutable.
119
210
  */
@@ -121,9 +212,17 @@ export const isMutable = EchoSchema.isMutable;
121
212
 
122
213
  export { SpaceId, ObjectId, DXN } from '@dxos/keys';
123
214
 
124
- export {
125
- //
215
+ export interface Expando extends OfKind<EchoSchema.EntityKind.Object> {
216
+ [key: string]: any;
217
+ }
218
+
219
+ export const Expando: Schema.Schema<
126
220
  Expando,
221
+ Simplify<ObjJsonProps & { [key: string]: any }>,
222
+ never
223
+ > = EchoSchema.Expando as any;
224
+
225
+ export {
127
226
  // TODO(burdon): Standardize.
128
227
  Format,
129
228
  JsonSchemaType as JsonSchema,
package/src/index.ts CHANGED
@@ -9,5 +9,5 @@ export * as Relation from './Relation';
9
9
  export * as Type from './Type';
10
10
 
11
11
  export { DXN } from '@dxos/keys';
12
- export { Filter, Query } from '@dxos/echo-schema';
12
+ export { Filter, Query } from './query';
13
13
  export { type Live } from '@dxos/live-object';