@dxos/echo-protocol 0.8.4-main.d05539e30a → 0.8.4-main.d9fc60f731
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/neutral/index.mjs +45 -164
- package/dist/lib/neutral/index.mjs.map +3 -3
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/types/src/document-structure.d.ts +59 -34
- package/dist/types/src/document-structure.d.ts.map +1 -1
- package/dist/types/src/query/ast.d.ts +68 -31
- package/dist/types/src/query/ast.d.ts.map +1 -1
- package/dist/types/src/reference.d.ts +11 -65
- package/dist/types/src/reference.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/src/document-structure.ts +69 -37
- package/src/query/ast.ts +43 -26
- package/src/reference.ts +12 -160
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/echo-protocol",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.d9fc60f731",
|
|
4
4
|
"description": "Core ECHO APIs.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -25,12 +25,12 @@
|
|
|
25
25
|
"src"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"effect": "3.
|
|
29
|
-
"@dxos/crypto": "0.8.4-main.
|
|
30
|
-
"@dxos/
|
|
31
|
-
"@dxos/
|
|
32
|
-
"@dxos/
|
|
33
|
-
"@dxos/
|
|
28
|
+
"effect": "3.21.2",
|
|
29
|
+
"@dxos/crypto": "0.8.4-main.d9fc60f731",
|
|
30
|
+
"@dxos/invariant": "0.8.4-main.d9fc60f731",
|
|
31
|
+
"@dxos/protocols": "0.8.4-main.d9fc60f731",
|
|
32
|
+
"@dxos/keys": "0.8.4-main.d9fc60f731",
|
|
33
|
+
"@dxos/util": "0.8.4-main.d9fc60f731"
|
|
34
34
|
},
|
|
35
35
|
"publishConfig": {
|
|
36
36
|
"access": "public"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { invariant } from '@dxos/invariant';
|
|
6
|
-
import type {
|
|
6
|
+
import type { EntityId, URI } from '@dxos/keys';
|
|
7
7
|
import { visitValues } from '@dxos/util';
|
|
8
8
|
|
|
9
9
|
import { type RawString } from './automerge';
|
|
@@ -19,8 +19,8 @@ export type SpaceState = {
|
|
|
19
19
|
/**
|
|
20
20
|
* Array indexes get converted to strings.
|
|
21
21
|
*/
|
|
22
|
-
export type
|
|
23
|
-
export type
|
|
22
|
+
export type EntityProp = string;
|
|
23
|
+
export type EntityPropPath = EntityProp[];
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Link to all documents that hold objects in the space.
|
|
@@ -35,13 +35,13 @@ export interface DatabaseDirectory {
|
|
|
35
35
|
* Objects inlined in the current document.
|
|
36
36
|
*/
|
|
37
37
|
objects?: {
|
|
38
|
-
[id: string]:
|
|
38
|
+
[id: string]: EntityStructure;
|
|
39
39
|
};
|
|
40
40
|
/**
|
|
41
41
|
* Object id points to an automerge doc url where the object is embedded.
|
|
42
42
|
*/
|
|
43
43
|
links?: {
|
|
44
|
-
[
|
|
44
|
+
[echoUri: string]: string | RawString;
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
/**
|
|
@@ -67,11 +67,11 @@ export const DatabaseDirectory = Object.freeze({
|
|
|
67
67
|
return rawKey;
|
|
68
68
|
},
|
|
69
69
|
|
|
70
|
-
getInlineObject: (doc: DatabaseDirectory, id:
|
|
70
|
+
getInlineObject: (doc: DatabaseDirectory, id: EntityId): EntityStructure | undefined => {
|
|
71
71
|
return doc.objects?.[id];
|
|
72
72
|
},
|
|
73
73
|
|
|
74
|
-
getLink: (doc: DatabaseDirectory, id:
|
|
74
|
+
getLink: (doc: DatabaseDirectory, id: EntityId): string | undefined => {
|
|
75
75
|
return doc.links?.[id]?.toString();
|
|
76
76
|
},
|
|
77
77
|
|
|
@@ -81,7 +81,7 @@ export const DatabaseDirectory = Object.freeze({
|
|
|
81
81
|
links,
|
|
82
82
|
}: {
|
|
83
83
|
spaceKey: string;
|
|
84
|
-
objects?: Record<string,
|
|
84
|
+
objects?: Record<string, EntityStructure>;
|
|
85
85
|
links?: Record<string, RawString>;
|
|
86
86
|
}): DatabaseDirectory => ({
|
|
87
87
|
access: {
|
|
@@ -95,11 +95,11 @@ export const DatabaseDirectory = Object.freeze({
|
|
|
95
95
|
/**
|
|
96
96
|
* Representation of an ECHO object in an AM document.
|
|
97
97
|
*/
|
|
98
|
-
export type
|
|
98
|
+
export type EntityStructure = {
|
|
99
99
|
// TODO(dmaretskyi): Missing in some cases.
|
|
100
|
-
system?:
|
|
100
|
+
system?: EntitySystem;
|
|
101
101
|
|
|
102
|
-
meta:
|
|
102
|
+
meta: EntityMeta;
|
|
103
103
|
/**
|
|
104
104
|
* User-defined data.
|
|
105
105
|
* Adheres to schema in `system.type`
|
|
@@ -107,46 +107,46 @@ export type ObjectStructure = {
|
|
|
107
107
|
data: Record<string, any>;
|
|
108
108
|
};
|
|
109
109
|
|
|
110
|
-
// Helper methods to interact with the {@link
|
|
111
|
-
export const
|
|
110
|
+
// Helper methods to interact with the {@link EntityStructure}.
|
|
111
|
+
export const EntityStructure = Object.freeze({
|
|
112
112
|
/**
|
|
113
113
|
* @throws On invalid object structure.
|
|
114
114
|
*/
|
|
115
|
-
getTypeReference: (object:
|
|
115
|
+
getTypeReference: (object: EntityStructure): EncodedReference | undefined => {
|
|
116
116
|
return object.system?.type;
|
|
117
117
|
},
|
|
118
118
|
|
|
119
119
|
/**
|
|
120
120
|
* @throws On invalid object structure.
|
|
121
121
|
*/
|
|
122
|
-
getEntityKind: (object:
|
|
122
|
+
getEntityKind: (object: EntityStructure): 'object' | 'relation' | 'type' => {
|
|
123
123
|
const kind = object.system?.kind ?? 'object';
|
|
124
|
-
invariant(kind === 'object' || kind === 'relation', 'Invalid kind');
|
|
124
|
+
invariant(kind === 'object' || kind === 'relation' || kind === 'type', 'Invalid kind');
|
|
125
125
|
return kind;
|
|
126
126
|
},
|
|
127
127
|
|
|
128
|
-
isDeleted: (object:
|
|
128
|
+
isDeleted: (object: EntityStructure): boolean => {
|
|
129
129
|
return object.system?.deleted ?? false;
|
|
130
130
|
},
|
|
131
131
|
|
|
132
|
-
getRelationSource: (object:
|
|
132
|
+
getRelationSource: (object: EntityStructure): EncodedReference | undefined => {
|
|
133
133
|
return object.system?.source;
|
|
134
134
|
},
|
|
135
135
|
|
|
136
|
-
getRelationTarget: (object:
|
|
136
|
+
getRelationTarget: (object: EntityStructure): EncodedReference | undefined => {
|
|
137
137
|
return object.system?.target;
|
|
138
138
|
},
|
|
139
139
|
|
|
140
|
-
getParent: (object:
|
|
140
|
+
getParent: (object: EntityStructure): EncodedReference | undefined => {
|
|
141
141
|
return object.system?.parent;
|
|
142
142
|
},
|
|
143
143
|
|
|
144
144
|
/**
|
|
145
145
|
* @returns All references in the data section of the object.
|
|
146
146
|
*/
|
|
147
|
-
getAllOutgoingReferences: (object:
|
|
148
|
-
const references: { path:
|
|
149
|
-
const visit = (path:
|
|
147
|
+
getAllOutgoingReferences: (object: EntityStructure): { path: EntityPropPath; reference: EncodedReference }[] => {
|
|
148
|
+
const references: { path: EntityPropPath; reference: EncodedReference }[] = [];
|
|
149
|
+
const visit = (path: EntityPropPath, value: unknown) => {
|
|
150
150
|
if (isEncodedReference(value)) {
|
|
151
151
|
references.push({ path, reference: value });
|
|
152
152
|
} else {
|
|
@@ -157,7 +157,7 @@ export const ObjectStructure = Object.freeze({
|
|
|
157
157
|
return references;
|
|
158
158
|
},
|
|
159
159
|
|
|
160
|
-
getTags: (object:
|
|
160
|
+
getTags: (object: EntityStructure): (EncodedReference | string)[] => {
|
|
161
161
|
return object.meta.tags ?? [];
|
|
162
162
|
},
|
|
163
163
|
|
|
@@ -166,11 +166,11 @@ export const ObjectStructure = Object.freeze({
|
|
|
166
166
|
data,
|
|
167
167
|
keys,
|
|
168
168
|
}: {
|
|
169
|
-
type:
|
|
169
|
+
type: URI.URI;
|
|
170
170
|
deleted?: boolean;
|
|
171
171
|
keys?: ForeignKey[];
|
|
172
172
|
data?: unknown;
|
|
173
|
-
}):
|
|
173
|
+
}): EntityStructure => {
|
|
174
174
|
return {
|
|
175
175
|
system: {
|
|
176
176
|
kind: 'object',
|
|
@@ -191,13 +191,13 @@ export const ObjectStructure = Object.freeze({
|
|
|
191
191
|
keys,
|
|
192
192
|
data,
|
|
193
193
|
}: {
|
|
194
|
-
type:
|
|
194
|
+
type: URI.URI;
|
|
195
195
|
source: EncodedReference;
|
|
196
196
|
target: EncodedReference;
|
|
197
197
|
deleted?: boolean;
|
|
198
198
|
keys?: ForeignKey[];
|
|
199
199
|
data?: unknown;
|
|
200
|
-
}):
|
|
200
|
+
}): EntityStructure => {
|
|
201
201
|
return {
|
|
202
202
|
system: {
|
|
203
203
|
kind: 'relation',
|
|
@@ -212,12 +212,25 @@ export const ObjectStructure = Object.freeze({
|
|
|
212
212
|
data: data ?? {},
|
|
213
213
|
};
|
|
214
214
|
},
|
|
215
|
+
|
|
216
|
+
makeType: ({ type, keys, data }: { type: URI.URI; keys?: ForeignKey[]; data?: unknown }): EntityStructure => {
|
|
217
|
+
return {
|
|
218
|
+
system: {
|
|
219
|
+
kind: 'type',
|
|
220
|
+
type: { '/': type },
|
|
221
|
+
},
|
|
222
|
+
meta: {
|
|
223
|
+
keys: keys ?? [],
|
|
224
|
+
},
|
|
225
|
+
data: data ?? {},
|
|
226
|
+
};
|
|
227
|
+
},
|
|
215
228
|
});
|
|
216
229
|
|
|
217
230
|
/**
|
|
218
231
|
* Echo object metadata.
|
|
219
232
|
*/
|
|
220
|
-
export type
|
|
233
|
+
export type EntityMeta = {
|
|
221
234
|
/**
|
|
222
235
|
* Foreign keys.
|
|
223
236
|
*/
|
|
@@ -225,11 +238,12 @@ export type ObjectMeta = {
|
|
|
225
238
|
|
|
226
239
|
/**
|
|
227
240
|
* Tags.
|
|
228
|
-
*
|
|
241
|
+
* Encoded references to Tag objects within the space.
|
|
229
242
|
*
|
|
230
|
-
* NOTE: Optional for backwards
|
|
243
|
+
* NOTE: Optional for backwards compatibility; legacy data may store bare DXN strings, which are
|
|
244
|
+
* upgraded to encoded references on read (see `object-core.ts`).
|
|
231
245
|
*/
|
|
232
|
-
tags?: string[];
|
|
246
|
+
tags?: (EncodedReference | string)[];
|
|
233
247
|
|
|
234
248
|
/**
|
|
235
249
|
* Fully-qualified registry key for the object (FQN format, e.g. `org.example.type.foo`).
|
|
@@ -242,20 +256,38 @@ export type ObjectMeta = {
|
|
|
242
256
|
* Must be a valid semver string (e.g. `1.2.3`).
|
|
243
257
|
*/
|
|
244
258
|
version?: string;
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Dictionary of annotations to this entity.
|
|
262
|
+
*
|
|
263
|
+
* NOTE: Optional for backwards compatibility. Values are arbitrary decoded automerge primitives;
|
|
264
|
+
* typed as `any` so `EntityStructure` stays assignable to `DecodedAutomergePrimaryValue`.
|
|
265
|
+
*/
|
|
266
|
+
annotations?: { readonly [key: string]: any };
|
|
245
267
|
};
|
|
246
268
|
|
|
247
269
|
/**
|
|
248
270
|
* Automerge object system properties.
|
|
249
271
|
* (Is automerge specific.)
|
|
250
272
|
*/
|
|
251
|
-
export type
|
|
273
|
+
export type EntitySystem = {
|
|
252
274
|
/**
|
|
253
|
-
* Entity kind.
|
|
275
|
+
* Entity kind. `'type'` covers persisted ECHO type definitions (instances of
|
|
276
|
+
* the `Type.Type` meta-schema); `'object'` / `'relation'` cover regular ECHO
|
|
277
|
+
* instances.
|
|
254
278
|
*/
|
|
255
|
-
kind?: 'object' | 'relation';
|
|
279
|
+
kind?: 'object' | 'relation' | 'type';
|
|
256
280
|
|
|
257
281
|
/**
|
|
258
|
-
* Object reference ('protobuf' protocol) type
|
|
282
|
+
* Object reference ('protobuf' protocol) type — DXN of the schema this
|
|
283
|
+
* entity instantiates.
|
|
284
|
+
*
|
|
285
|
+
* - For `kind === 'object'` / `'relation'` instances, this is the URI of the
|
|
286
|
+
* user-defined schema the entity was created from (e.g. `dxn:type:org.example.Person:1.0.0`).
|
|
287
|
+
* - For `kind === 'type'` entities (persisted Type.Type meta-instances) this
|
|
288
|
+
* is always the URI of the `TypeSchema` meta-schema itself
|
|
289
|
+
* (`dxn:org.dxos.type.schema:0.1.0`). The kind that the meta-instance
|
|
290
|
+
* _describes_ (object/relation/type) lives in `data.jsonSchema.entityKind`.
|
|
259
291
|
*/
|
|
260
292
|
type?: EncodedReference;
|
|
261
293
|
|
|
@@ -288,6 +320,6 @@ export const PROPERTY_ID = 'id';
|
|
|
288
320
|
|
|
289
321
|
/**
|
|
290
322
|
* Data namespace.
|
|
291
|
-
* The key on {@link
|
|
323
|
+
* The key on {@link EntityStructure} that contains the user-defined data.
|
|
292
324
|
*/
|
|
293
325
|
export const DATA_NAMESPACE = 'data';
|
package/src/query/ast.ts
CHANGED
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
import * as Match from 'effect/Match';
|
|
6
6
|
import * as Schema from 'effect/Schema';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { EID, EntityId, URI } from '@dxos/keys';
|
|
9
9
|
|
|
10
10
|
import { ForeignKey } from '../foreign-key';
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
// Type identifier URI — either a DXN (typename) or an EID (stored-schema-as-object).
|
|
13
|
+
// Matches the URI written into an object's `system.type` (see `getSchemaURI`). Null
|
|
14
|
+
// matches any type.
|
|
15
|
+
const TypenameSpecifier = Schema.Union(URI.Schema, Schema.Null);
|
|
15
16
|
|
|
16
17
|
// NOTE: This pattern with 3 definitions per schema is need to make the types opaque, and circular references in AST to not cause compiler errors.
|
|
17
18
|
|
|
@@ -26,7 +27,7 @@ const FilterObject_ = Schema.Struct({
|
|
|
26
27
|
|
|
27
28
|
typename: TypenameSpecifier,
|
|
28
29
|
|
|
29
|
-
id: Schema.optional(Schema.Array(
|
|
30
|
+
id: Schema.optional(Schema.Array(EntityId)),
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* Filter by property.
|
|
@@ -184,7 +185,7 @@ export const FilterOr: Schema.Schema<FilterOr> = FilterOr_;
|
|
|
184
185
|
const FilterChildOf_ = Schema.Struct({
|
|
185
186
|
type: Schema.Literal('child-of'),
|
|
186
187
|
/** Parent DXNs to match children of. */
|
|
187
|
-
parents: Schema.Array(
|
|
188
|
+
parents: Schema.Array(EID.Schema),
|
|
188
189
|
/** Whether to match transitively (grandchildren, etc.). Defaults to true. */
|
|
189
190
|
transitive: Schema.Boolean,
|
|
190
191
|
});
|
|
@@ -402,7 +403,7 @@ export const QueryFromClause_ = Schema.Struct({
|
|
|
402
403
|
query: Schema.suspend(() => Query),
|
|
403
404
|
from: Schema.Union(
|
|
404
405
|
Schema.TaggedStruct('scope', {
|
|
405
|
-
|
|
406
|
+
scopes: Schema.Array(Schema.suspend(() => Scope)),
|
|
406
407
|
}),
|
|
407
408
|
Schema.TaggedStruct('query', {
|
|
408
409
|
query: Schema.suspend(() => Query),
|
|
@@ -446,29 +447,45 @@ export const QueryOptions = Schema.Struct({
|
|
|
446
447
|
export interface QueryOptions extends Schema.Schema.Type<typeof QueryOptions> {}
|
|
447
448
|
|
|
448
449
|
/**
|
|
449
|
-
*
|
|
450
|
+
* Selects from a space (automerge documents).
|
|
451
|
+
* When `spaceId` is omitted, targets the owning space — i.e. the space of whichever
|
|
452
|
+
* database executes the query. This lets callers reference "this space" without
|
|
453
|
+
* having to look up its id.
|
|
454
|
+
* When `includeAllFeeds` is true, also selects from all feeds belonging to that space.
|
|
450
455
|
*/
|
|
451
|
-
export const
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
*/
|
|
457
|
-
spaceIds: Schema.optional(Schema.Array(Schema.String)),
|
|
456
|
+
export const SpaceScope = Schema.TaggedStruct('space', {
|
|
457
|
+
spaceId: Schema.optional(Schema.String),
|
|
458
|
+
includeAllFeeds: Schema.optional(Schema.Boolean),
|
|
459
|
+
});
|
|
460
|
+
export interface SpaceScope extends Schema.Schema.Type<typeof SpaceScope> {}
|
|
458
461
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
462
|
+
/**
|
|
463
|
+
* Selects from a specific feed (by its underlying queue DXN).
|
|
464
|
+
*/
|
|
465
|
+
export const FeedScope = Schema.TaggedStruct('feed', {
|
|
466
|
+
feedUri: Schema.String,
|
|
467
|
+
});
|
|
468
|
+
export interface FeedScope extends Schema.Schema.Type<typeof FeedScope> {}
|
|
463
469
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
+
/**
|
|
471
|
+
* Selects from a code-shipped object registry.
|
|
472
|
+
*
|
|
473
|
+
* - `'local'` — the in-process registry attached to the hypergraph.
|
|
474
|
+
* - `'remote'` — a future remote registry service (not yet implemented).
|
|
475
|
+
*
|
|
476
|
+
* To include both, add two separate `RegistryScope` entries to the `scopes` array.
|
|
477
|
+
*/
|
|
478
|
+
export const RegistryScope = Schema.TaggedStruct('registry', {
|
|
479
|
+
location: Schema.Literal('local', 'remote'),
|
|
470
480
|
});
|
|
471
|
-
export interface
|
|
481
|
+
export interface RegistryScope extends Schema.Schema.Type<typeof RegistryScope> {}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Specifies the scope of the data to query from.
|
|
485
|
+
* A `from` clause may carry multiple scopes; results are unioned across them.
|
|
486
|
+
*/
|
|
487
|
+
export const Scope = Schema.Union(SpaceScope, FeedScope, RegistryScope);
|
|
488
|
+
export type Scope = Schema.Schema.Type<typeof Scope>;
|
|
472
489
|
|
|
473
490
|
export const visit = (query: Query, visitor: (node: Query) => void) => {
|
|
474
491
|
visitor(query);
|
package/src/reference.ts
CHANGED
|
@@ -3,126 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { assertArgument } from '@dxos/invariant';
|
|
6
|
-
import {
|
|
7
|
-
import { type ObjectId } from '@dxos/protocols';
|
|
8
|
-
import { type Reference as ReferenceProto } from '@dxos/protocols/proto/dxos/echo/model/document';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Runtime representation of an reference in ECHO.
|
|
12
|
-
* Implemented as a DXN, but we might extend it to other URIs in the future.
|
|
13
|
-
* @deprecated Use `EncodedReference` instead.
|
|
14
|
-
*/
|
|
15
|
-
export class Reference {
|
|
16
|
-
/**
|
|
17
|
-
* Protocol references to runtime registered types.
|
|
18
|
-
* @deprecated
|
|
19
|
-
*/
|
|
20
|
-
static TYPE_PROTOCOL = 'protobuf';
|
|
21
|
-
|
|
22
|
-
static fromDXN(dxn: DXN): Reference {
|
|
23
|
-
switch (dxn.kind) {
|
|
24
|
-
case DXN.kind.TYPE:
|
|
25
|
-
return new Reference(dxn.parts[0], Reference.TYPE_PROTOCOL, 'dxos.org', dxn);
|
|
26
|
-
case DXN.kind.ECHO:
|
|
27
|
-
if (dxn.parts[0] === LOCAL_SPACE_TAG) {
|
|
28
|
-
return new Reference(dxn.parts[1], undefined, undefined, dxn);
|
|
29
|
-
} else {
|
|
30
|
-
return new Reference(dxn.parts[1], undefined, dxn.parts[0], dxn);
|
|
31
|
-
}
|
|
32
|
-
default:
|
|
33
|
-
return new Reference(dxn.parts[0], undefined, dxn.parts[0], dxn);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
static fromValue(value: ReferenceProto): Reference {
|
|
38
|
-
return new Reference(value.objectId, value.protocol, value.host);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Reference an object in the local space.
|
|
43
|
-
*/
|
|
44
|
-
static localObjectReference(objectId: ObjectId): Reference {
|
|
45
|
-
return new Reference(objectId);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @deprecated
|
|
50
|
-
*/
|
|
51
|
-
// TODO(dmaretskyi): Remove.
|
|
52
|
-
static fromLegacyTypename(type: string): Reference {
|
|
53
|
-
return new Reference(type, Reference.TYPE_PROTOCOL, 'dxos.org');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* @deprecated
|
|
58
|
-
*/
|
|
59
|
-
// TODO(dmaretskyi): Remove
|
|
60
|
-
static fromObjectIdAndSpaceKey(objectId: ObjectId, spaceKey: PublicKey): Reference {
|
|
61
|
-
// TODO(dmaretskyi): FIX ME! This should be a space ID not a space key.
|
|
62
|
-
return new Reference(objectId, undefined, spaceKey.toHex());
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// prettier-ignore
|
|
66
|
-
private constructor(
|
|
67
|
-
// TODO(dmaretskyi): Remove and just leave DXN.
|
|
68
|
-
private readonly _objectId: ObjectId,
|
|
69
|
-
private readonly _protocol?: string,
|
|
70
|
-
private readonly _host?: string,
|
|
71
|
-
private readonly _dxn?: DXN,
|
|
72
|
-
) {}
|
|
73
|
-
|
|
74
|
-
get dxn(): DXN | undefined {
|
|
75
|
-
return this._dxn;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* @deprecated
|
|
80
|
-
*/
|
|
81
|
-
// TODO(dmaretskyi): Remove.
|
|
82
|
-
get objectId(): ObjectId {
|
|
83
|
-
return this._objectId;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* @deprecated
|
|
88
|
-
*/
|
|
89
|
-
// TODO(dmaretskyi): Remove.
|
|
90
|
-
get protocol(): string | undefined {
|
|
91
|
-
return this._protocol;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* @deprecated
|
|
96
|
-
*/
|
|
97
|
-
// TODO(dmaretskyi): Remove.
|
|
98
|
-
get host(): string | undefined {
|
|
99
|
-
return this._host;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
encode(): ReferenceProto {
|
|
103
|
-
return { objectId: this.objectId, host: this.host, protocol: this.protocol };
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// TODO(dmaretskyi): Remove in favor of `reference.dxn`.
|
|
107
|
-
toDXN(): DXN {
|
|
108
|
-
if (this._dxn) {
|
|
109
|
-
return this._dxn;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (this.protocol === Reference.TYPE_PROTOCOL) {
|
|
113
|
-
return new DXN(DXN.kind.TYPE, [this.objectId]);
|
|
114
|
-
} else {
|
|
115
|
-
if (this.host) {
|
|
116
|
-
// Host is assumed to be the space key.
|
|
117
|
-
// The DXN should actually have the space ID.
|
|
118
|
-
// TODO(dmaretskyi): Migrate to space id.
|
|
119
|
-
return new DXN(DXN.kind.ECHO, [this.host, this.objectId]);
|
|
120
|
-
} else {
|
|
121
|
-
return new DXN(DXN.kind.ECHO, [LOCAL_SPACE_TAG, this.objectId]);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
6
|
+
import { URI } from '@dxos/keys';
|
|
126
7
|
|
|
127
8
|
// TODO(dmaretskyi): Is this used anywhere?
|
|
128
9
|
export const REFERENCE_TYPE_TAG = 'dxos.echo.model.document.Reference';
|
|
@@ -131,55 +12,26 @@ export const REFERENCE_TYPE_TAG = 'dxos.echo.model.document.Reference';
|
|
|
131
12
|
* Reference as it is stored in Automerge document.
|
|
132
13
|
*/
|
|
133
14
|
export type EncodedReference = {
|
|
134
|
-
'/':
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* @deprecated Use `EncodedReference.fromDXN` instead.
|
|
139
|
-
*/
|
|
140
|
-
export const encodeReference = (reference: Reference): EncodedReference => ({
|
|
141
|
-
'/': reference.toDXN().toString(),
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* @deprecated Use `EncodedReference.toDXN` instead.
|
|
146
|
-
*/
|
|
147
|
-
export const decodeReference = (value: any) => {
|
|
148
|
-
if (typeof value !== 'object' || value === null || typeof value['/'] !== 'string') {
|
|
149
|
-
throw new Error('Invalid reference');
|
|
150
|
-
}
|
|
151
|
-
const dxnString = value['/'];
|
|
152
|
-
|
|
153
|
-
if (
|
|
154
|
-
dxnString.length % 2 === 0 &&
|
|
155
|
-
dxnString.slice(0, dxnString.length / 2) === dxnString.slice(dxnString.length / 2) &&
|
|
156
|
-
dxnString.includes('dxn:echo')
|
|
157
|
-
) {
|
|
158
|
-
throw new Error('Automerge bug detected!');
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return Reference.fromDXN(DXN.parse(dxnString));
|
|
15
|
+
'/': URI.URI;
|
|
162
16
|
};
|
|
163
17
|
|
|
164
|
-
/**
|
|
165
|
-
* @deprecated Use `EncodedReference.isEncodedReference` instead.
|
|
166
|
-
*/
|
|
167
18
|
export const isEncodedReference = (value: any): value is EncodedReference =>
|
|
168
19
|
typeof value === 'object' && value !== null && Object.keys(value).length === 1 && typeof value['/'] === 'string';
|
|
169
20
|
|
|
170
21
|
export const EncodedReference = Object.freeze({
|
|
171
22
|
isEncodedReference,
|
|
172
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Returns the opaque URI stored in the encoded reference (any scheme: `echo:` or `dxn:`).
|
|
25
|
+
* Consumers can narrow with `EID.isEID(uri)` / `DXN.isDXN(uri)`.
|
|
26
|
+
*/
|
|
27
|
+
toURI: (value: EncodedReference): URI.URI => {
|
|
173
28
|
assertArgument(isEncodedReference(value), 'value', 'invalid reference');
|
|
174
29
|
return value['/'];
|
|
175
30
|
},
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
return { '/':
|
|
181
|
-
},
|
|
182
|
-
fromLegacyTypename: (typename: string): EncodedReference => {
|
|
183
|
-
return { '/': DXN.fromTypename(typename).toString() };
|
|
31
|
+
/**
|
|
32
|
+
* Creates an encoded reference from an opaque URI.
|
|
33
|
+
*/
|
|
34
|
+
fromURI: (uri: URI.URI): EncodedReference => {
|
|
35
|
+
return { '/': uri };
|
|
184
36
|
},
|
|
185
37
|
});
|