@dxos/echo-pipeline 0.8.3 → 0.8.4-main.1068cf700f
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/chunk-FJPXA75J.mjs +235 -0
- package/dist/lib/neutral/chunk-FJPXA75J.mjs.map +7 -0
- package/dist/lib/{browser/chunk-35I6ERLG.mjs → neutral/chunk-WIQUYO7H.mjs} +300 -213
- package/dist/lib/neutral/chunk-WIQUYO7H.mjs.map +7 -0
- package/dist/lib/{browser → neutral}/filter/index.mjs +3 -2
- package/dist/lib/{browser → neutral}/index.mjs +2832 -946
- package/dist/lib/neutral/index.mjs.map +7 -0
- package/dist/lib/neutral/meta.json +1 -0
- package/dist/lib/{browser → neutral}/testing/index.mjs +73 -224
- package/dist/lib/neutral/testing/index.mjs.map +7 -0
- package/dist/types/src/automerge/automerge-host.d.ts +53 -42
- package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
- package/dist/types/src/automerge/automerge-repo.test.d.ts +1 -1
- package/dist/types/src/automerge/automerge-repo.test.d.ts.map +1 -1
- package/dist/types/src/automerge/collection-synchronizer.d.ts +6 -4
- package/dist/types/src/automerge/collection-synchronizer.d.ts.map +1 -1
- package/dist/types/src/automerge/echo-network-adapter.d.ts +22 -10
- package/dist/types/src/automerge/echo-network-adapter.d.ts.map +1 -1
- package/dist/types/src/automerge/echo-replicator.d.ts +37 -15
- package/dist/types/src/automerge/echo-replicator.d.ts.map +1 -1
- package/dist/types/src/automerge/heads-store.d.ts +9 -2
- package/dist/types/src/automerge/heads-store.d.ts.map +1 -1
- package/dist/types/src/automerge/index.d.ts +1 -1
- package/dist/types/src/automerge/index.d.ts.map +1 -1
- package/dist/types/src/automerge/leveldb-storage-adapter.d.ts +5 -5
- package/dist/types/src/automerge/leveldb-storage-adapter.d.ts.map +1 -1
- package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts +9 -8
- package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts.map +1 -1
- package/dist/types/src/automerge/mesh-echo-replicator.d.ts +5 -5
- package/dist/types/src/automerge/mesh-echo-replicator.d.ts.map +1 -1
- package/dist/types/src/common/codec.d.ts +1 -1
- package/dist/types/src/common/codec.d.ts.map +1 -1
- package/dist/types/src/db-host/automerge-data-source.d.ts +34 -0
- package/dist/types/src/db-host/automerge-data-source.d.ts.map +1 -0
- package/dist/types/src/db-host/automerge-data-source.test.d.ts +2 -0
- package/dist/types/src/db-host/automerge-data-source.test.d.ts.map +1 -0
- package/dist/types/src/db-host/data-service.d.ts +5 -4
- package/dist/types/src/db-host/data-service.d.ts.map +1 -1
- package/dist/types/src/db-host/database-root.d.ts.map +1 -1
- package/dist/types/src/db-host/documents-synchronizer.d.ts +6 -5
- package/dist/types/src/db-host/documents-synchronizer.d.ts.map +1 -1
- package/dist/types/src/db-host/echo-host.d.ts +44 -23
- package/dist/types/src/db-host/echo-host.d.ts.map +1 -1
- package/dist/types/src/db-host/index.d.ts +1 -0
- package/dist/types/src/db-host/index.d.ts.map +1 -1
- package/dist/types/src/db-host/local-queue-service.d.ts +16 -0
- package/dist/types/src/db-host/local-queue-service.d.ts.map +1 -0
- package/dist/types/src/db-host/query-service.d.ts +14 -9
- package/dist/types/src/db-host/query-service.d.ts.map +1 -1
- package/dist/types/src/db-host/queue-data-source.d.ts +28 -0
- package/dist/types/src/db-host/queue-data-source.d.ts.map +1 -0
- package/dist/types/src/db-host/queue-service.test.d.ts +2 -0
- package/dist/types/src/db-host/queue-service.test.d.ts.map +1 -0
- package/dist/types/src/db-host/space-state-manager.d.ts +2 -1
- package/dist/types/src/db-host/space-state-manager.d.ts.map +1 -1
- package/dist/types/src/db-host/stub.d.ts +10 -0
- package/dist/types/src/db-host/stub.d.ts.map +1 -0
- package/dist/types/src/edge/echo-edge-replicator.d.ts +8 -6
- package/dist/types/src/edge/echo-edge-replicator.d.ts.map +1 -1
- package/dist/types/src/filter/filter-match.d.ts +4 -1
- package/dist/types/src/filter/filter-match.d.ts.map +1 -1
- package/dist/types/src/metadata/metadata-store.d.ts +1 -1
- package/dist/types/src/metadata/metadata-store.d.ts.map +1 -1
- package/dist/types/src/pipeline/pipeline.d.ts +3 -3
- package/dist/types/src/pipeline/pipeline.d.ts.map +1 -1
- package/dist/types/src/query/errors.d.ts +21 -9
- package/dist/types/src/query/errors.d.ts.map +1 -1
- package/dist/types/src/query/plan.d.ts +57 -5
- package/dist/types/src/query/plan.d.ts.map +1 -1
- package/dist/types/src/query/query-executor.d.ts +49 -10
- package/dist/types/src/query/query-executor.d.ts.map +1 -1
- package/dist/types/src/query/query-planner.d.ts +9 -0
- package/dist/types/src/query/query-planner.d.ts.map +1 -1
- package/dist/types/src/space/admission-discovery-extension.d.ts.map +1 -1
- package/dist/types/src/space/auth.d.ts +3 -3
- package/dist/types/src/space/auth.d.ts.map +1 -1
- package/dist/types/src/space/control-pipeline.d.ts +3 -3
- package/dist/types/src/space/control-pipeline.d.ts.map +1 -1
- package/dist/types/src/space/space-manager.d.ts +7 -7
- package/dist/types/src/space/space-manager.d.ts.map +1 -1
- package/dist/types/src/space/space-protocol.d.ts +6 -6
- package/dist/types/src/space/space-protocol.d.ts.map +1 -1
- package/dist/types/src/space/space.d.ts +4 -4
- package/dist/types/src/space/space.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +0 -2
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/test-agent-builder.d.ts +2 -2
- package/dist/types/src/testing/test-agent-builder.d.ts.map +1 -1
- package/dist/types/src/testing/test-network-adapter.d.ts +1 -1
- package/dist/types/src/testing/test-network-adapter.d.ts.map +1 -1
- package/dist/types/src/testing/test-replicator.d.ts +14 -13
- package/dist/types/src/testing/test-replicator.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +1 -1
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +53 -45
- package/src/automerge/automerge-host.test.ts +55 -24
- package/src/automerge/automerge-host.ts +399 -126
- package/src/automerge/automerge-repo.test.ts +214 -46
- package/src/automerge/collection-synchronizer.test.ts +22 -15
- package/src/automerge/collection-synchronizer.ts +57 -22
- package/src/automerge/echo-data-monitor.ts +1 -1
- package/src/automerge/echo-network-adapter.test.ts +3 -3
- package/src/automerge/echo-network-adapter.ts +73 -28
- package/src/automerge/echo-replicator.ts +40 -15
- package/src/automerge/heads-store.ts +42 -3
- package/src/automerge/index.ts +1 -1
- package/src/automerge/leveldb-storage-adapter.ts +11 -11
- package/src/automerge/mesh-echo-replicator-connection.ts +12 -8
- package/src/automerge/mesh-echo-replicator.ts +15 -11
- package/src/automerge/storage-adapter.test.ts +1 -1
- package/src/common/space-id.ts +1 -1
- package/src/db-host/automerge-data-source.test.ts +292 -0
- package/src/db-host/automerge-data-source.ts +144 -0
- package/src/db-host/data-service.ts +19 -20
- package/src/db-host/database-root.ts +2 -2
- package/src/db-host/documents-synchronizer.test.ts +73 -13
- package/src/db-host/documents-synchronizer.ts +58 -44
- package/src/db-host/echo-host.ts +194 -84
- package/src/db-host/index.ts +1 -0
- package/src/db-host/local-queue-service.ts +147 -0
- package/src/db-host/query-service.ts +28 -95
- package/src/db-host/queue-data-source.ts +132 -0
- package/src/db-host/queue-service.test.ts +145 -0
- package/src/db-host/space-state-manager.ts +6 -2
- package/src/db-host/stub.ts +28 -0
- package/src/edge/echo-edge-replicator.test.ts +8 -6
- package/src/edge/echo-edge-replicator.ts +124 -42
- package/src/filter/filter-match.test.ts +58 -32
- package/src/filter/filter-match.ts +163 -15
- package/src/metadata/metadata-store.ts +8 -5
- package/src/pipeline/pipeline-stress.test.ts +4 -2
- package/src/pipeline/pipeline.test.ts +3 -2
- package/src/pipeline/pipeline.ts +10 -7
- package/src/query/errors.ts +3 -1
- package/src/query/plan.ts +75 -5
- package/src/query/query-executor.ts +812 -117
- package/src/query/query-planner.test.ts +652 -34
- package/src/query/query-planner.ts +276 -13
- package/src/space/admission-discovery-extension.ts +3 -3
- package/src/space/auth.ts +6 -6
- package/src/space/control-pipeline.test.ts +4 -3
- package/src/space/control-pipeline.ts +11 -8
- package/src/space/space-manager.browser.test.ts +1 -1
- package/src/space/space-manager.ts +11 -10
- package/src/space/space-protocol.browser.test.ts +2 -2
- package/src/space/space-protocol.test.ts +3 -2
- package/src/space/space-protocol.ts +17 -14
- package/src/space/space.test.ts +1 -1
- package/src/space/space.ts +6 -5
- package/src/testing/index.ts +0 -2
- package/src/testing/test-agent-builder.ts +4 -3
- package/src/testing/test-network-adapter.ts +16 -3
- package/src/testing/test-replicator.ts +23 -18
- package/src/util.ts +7 -3
- package/dist/lib/browser/chunk-35I6ERLG.mjs.map +0 -7
- package/dist/lib/browser/chunk-CGS2ULMK.mjs +0 -11
- package/dist/lib/browser/chunk-CGS2ULMK.mjs.map +0 -7
- package/dist/lib/browser/chunk-TQJTKNMS.mjs +0 -126
- package/dist/lib/browser/chunk-TQJTKNMS.mjs.map +0 -7
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/testing/index.mjs.map +0 -7
- package/dist/lib/node/chunk-HOPOFWAL.cjs +0 -147
- package/dist/lib/node/chunk-HOPOFWAL.cjs.map +0 -7
- package/dist/lib/node/chunk-JXX6LF5U.cjs +0 -2084
- package/dist/lib/node/chunk-JXX6LF5U.cjs.map +0 -7
- package/dist/lib/node/chunk-Q7SFCCGT.cjs +0 -33
- package/dist/lib/node/chunk-Q7SFCCGT.cjs.map +0 -7
- package/dist/lib/node/filter/index.cjs +0 -32
- package/dist/lib/node/filter/index.cjs.map +0 -7
- package/dist/lib/node/index.cjs +0 -4699
- package/dist/lib/node/index.cjs.map +0 -7
- package/dist/lib/node/meta.json +0 -1
- package/dist/lib/node/testing/index.cjs +0 -753
- package/dist/lib/node/testing/index.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-5BHLPT24.mjs +0 -2067
- package/dist/lib/node-esm/chunk-5BHLPT24.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-RVK35BS7.mjs +0 -126
- package/dist/lib/node-esm/chunk-RVK35BS7.mjs.map +0 -7
- package/dist/lib/node-esm/filter/index.mjs +0 -11
- package/dist/lib/node-esm/filter/index.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -4743
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/testing/index.mjs +0 -742
- package/dist/lib/node-esm/testing/index.mjs.map +0 -7
- package/dist/types/src/db-host/documents-iterator.d.ts +0 -7
- package/dist/types/src/db-host/documents-iterator.d.ts.map +0 -1
- package/dist/types/src/testing/test-data.d.ts +0 -18
- package/dist/types/src/testing/test-data.d.ts.map +0 -1
- package/dist/types/src/testing/test-schema.d.ts +0 -37
- package/dist/types/src/testing/test-schema.d.ts.map +0 -1
- package/src/db-host/documents-iterator.ts +0 -74
- package/src/testing/test-data.ts +0 -127
- package/src/testing/test-schema.ts +0 -53
- /package/dist/lib/{browser → neutral}/filter/index.mjs.map +0 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { Order } from '@dxos/echo';
|
|
5
6
|
import { type QueryAST } from '@dxos/echo-protocol';
|
|
6
7
|
import { invariant } from '@dxos/invariant';
|
|
7
8
|
import type { DXN, SpaceId } from '@dxos/keys';
|
|
@@ -35,6 +36,8 @@ export class QueryPlanner {
|
|
|
35
36
|
let plan = this._generate(query, { ...DEFAULT_CONTEXT, originalQuery: query });
|
|
36
37
|
plan = this._optimizeEmptyFilters(plan);
|
|
37
38
|
plan = this._optimizeSoloUnions(plan);
|
|
39
|
+
plan = this._ensureOrderStep(plan);
|
|
40
|
+
plan = this._optimizeLimits(plan);
|
|
38
41
|
return plan;
|
|
39
42
|
}
|
|
40
43
|
|
|
@@ -54,12 +57,19 @@ export class QueryPlanner {
|
|
|
54
57
|
return this._generateRelationTraversalClause(query, context);
|
|
55
58
|
case 'reference-traversal':
|
|
56
59
|
return this._generateReferenceTraversalClause(query, context);
|
|
60
|
+
case 'hierarchy-traversal':
|
|
61
|
+
return this._generateHierarchyTraversalClause(query, context);
|
|
57
62
|
case 'union':
|
|
58
63
|
return this._generateUnionClause(query, context);
|
|
59
64
|
case 'set-difference':
|
|
60
65
|
return this._generateSetDifferenceClause(query, context);
|
|
66
|
+
case 'order':
|
|
67
|
+
return this._generateOrderClause(query, context);
|
|
68
|
+
case 'limit':
|
|
69
|
+
return this._generateLimitClause(query, context);
|
|
61
70
|
default:
|
|
62
|
-
throw new QueryError(
|
|
71
|
+
throw new QueryError({
|
|
72
|
+
message: `Unsupported query type: ${(query as any).type}`,
|
|
63
73
|
context: { query: context.originalQuery },
|
|
64
74
|
});
|
|
65
75
|
}
|
|
@@ -72,6 +82,12 @@ export class QueryPlanner {
|
|
|
72
82
|
if (query.options.spaceIds) {
|
|
73
83
|
newContext.selectionSpaces = query.options.spaceIds as readonly SpaceId[];
|
|
74
84
|
}
|
|
85
|
+
if (query.options.allQueuesFromSpaces !== undefined) {
|
|
86
|
+
newContext.selectionAllQueuesFromSpaces = query.options.allQueuesFromSpaces;
|
|
87
|
+
}
|
|
88
|
+
if (query.options.queues) {
|
|
89
|
+
newContext.selectionQueues = query.options.queues as readonly DXN.String[];
|
|
90
|
+
}
|
|
75
91
|
if (query.options.deleted) {
|
|
76
92
|
newContext.deletedHandling = query.options.deleted;
|
|
77
93
|
}
|
|
@@ -86,6 +102,7 @@ export class QueryPlanner {
|
|
|
86
102
|
// TODO(dmaretskyi): If the tip of the query ast is a [select, ...filter] shape we can reorder the filters so the query is most efficient.
|
|
87
103
|
private _generateSelectionFromFilter(filter: QueryAST.Filter, context: GenerationContext): QueryPlan.Plan {
|
|
88
104
|
switch (filter.type) {
|
|
105
|
+
// Props
|
|
89
106
|
case 'object': {
|
|
90
107
|
if (
|
|
91
108
|
context.selectionInverted &&
|
|
@@ -102,7 +119,10 @@ export class QueryPlanner {
|
|
|
102
119
|
]);
|
|
103
120
|
}
|
|
104
121
|
if (context.selectionInverted) {
|
|
105
|
-
throw new QueryError(
|
|
122
|
+
throw new QueryError({
|
|
123
|
+
message: 'Query too complex',
|
|
124
|
+
context: { query: context.originalQuery },
|
|
125
|
+
});
|
|
106
126
|
}
|
|
107
127
|
|
|
108
128
|
// Try to utilize indexes during selection, prioritizing selecting by id, then by typename.
|
|
@@ -112,6 +132,8 @@ export class QueryPlanner {
|
|
|
112
132
|
{
|
|
113
133
|
_tag: 'SelectStep',
|
|
114
134
|
spaces: context.selectionSpaces,
|
|
135
|
+
allQueuesFromSpaces: context.selectionAllQueuesFromSpaces,
|
|
136
|
+
queues: context.selectionQueues,
|
|
115
137
|
selector: {
|
|
116
138
|
_tag: 'IdSelector',
|
|
117
139
|
objectIds: filter.id,
|
|
@@ -128,6 +150,8 @@ export class QueryPlanner {
|
|
|
128
150
|
{
|
|
129
151
|
_tag: 'SelectStep',
|
|
130
152
|
spaces: context.selectionSpaces,
|
|
153
|
+
allQueuesFromSpaces: context.selectionAllQueuesFromSpaces,
|
|
154
|
+
queues: context.selectionQueues,
|
|
131
155
|
selector: {
|
|
132
156
|
_tag: 'TypeSelector',
|
|
133
157
|
typename: [filter.typename as DXN.String],
|
|
@@ -135,9 +159,10 @@ export class QueryPlanner {
|
|
|
135
159
|
},
|
|
136
160
|
},
|
|
137
161
|
...this._generateDeletedHandlingSteps(context),
|
|
162
|
+
// TODO(dmaretskyi): Normally we could skip filtering by typename here, but since the index does not separate schema versions, we need to do additional filter to only select the correct version.
|
|
138
163
|
{
|
|
139
164
|
_tag: 'FilterStep',
|
|
140
|
-
filter: { ...filter
|
|
165
|
+
filter: { ...filter },
|
|
141
166
|
},
|
|
142
167
|
]);
|
|
143
168
|
} else {
|
|
@@ -145,6 +170,8 @@ export class QueryPlanner {
|
|
|
145
170
|
{
|
|
146
171
|
_tag: 'SelectStep',
|
|
147
172
|
spaces: context.selectionSpaces,
|
|
173
|
+
allQueuesFromSpaces: context.selectionAllQueuesFromSpaces,
|
|
174
|
+
queues: context.selectionQueues,
|
|
148
175
|
selector: {
|
|
149
176
|
_tag: 'WildcardSelector',
|
|
150
177
|
},
|
|
@@ -157,44 +184,76 @@ export class QueryPlanner {
|
|
|
157
184
|
]);
|
|
158
185
|
}
|
|
159
186
|
}
|
|
187
|
+
|
|
188
|
+
// Tag
|
|
189
|
+
case 'tag': {
|
|
190
|
+
return QueryPlan.Plan.make([
|
|
191
|
+
{
|
|
192
|
+
_tag: 'SelectStep',
|
|
193
|
+
spaces: context.selectionSpaces,
|
|
194
|
+
allQueuesFromSpaces: context.selectionAllQueuesFromSpaces,
|
|
195
|
+
queues: context.selectionQueues,
|
|
196
|
+
selector: {
|
|
197
|
+
_tag: 'WildcardSelector',
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
...this._generateDeletedHandlingSteps(context),
|
|
201
|
+
{
|
|
202
|
+
_tag: 'FilterStep',
|
|
203
|
+
filter: { ...filter },
|
|
204
|
+
},
|
|
205
|
+
]);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Text
|
|
160
209
|
case 'text-search': {
|
|
161
210
|
return QueryPlan.Plan.make([
|
|
162
211
|
{
|
|
163
212
|
_tag: 'SelectStep',
|
|
164
213
|
spaces: context.selectionSpaces,
|
|
214
|
+
allQueuesFromSpaces: context.selectionAllQueuesFromSpaces,
|
|
215
|
+
queues: context.selectionQueues,
|
|
165
216
|
selector: {
|
|
166
217
|
_tag: 'TextSelector',
|
|
167
218
|
text: filter.text,
|
|
168
219
|
searchKind: filter.searchKind ?? this._options.defaultTextSearchKind,
|
|
220
|
+
typename: null,
|
|
169
221
|
},
|
|
170
222
|
},
|
|
171
223
|
...this._generateDeletedHandlingSteps(context),
|
|
172
224
|
]);
|
|
173
225
|
}
|
|
226
|
+
|
|
227
|
+
// Compare
|
|
174
228
|
case 'compare':
|
|
175
|
-
throw new QueryError('Query too complex',
|
|
229
|
+
throw new QueryError({ message: 'Query too complex', context: { query: context.originalQuery } });
|
|
176
230
|
case 'in':
|
|
177
|
-
throw new QueryError('Query too complex',
|
|
231
|
+
throw new QueryError({ message: 'Query too complex', context: { query: context.originalQuery } });
|
|
178
232
|
case 'range':
|
|
179
|
-
throw new QueryError('Query too complex',
|
|
233
|
+
throw new QueryError({ message: 'Query too complex', context: { query: context.originalQuery } });
|
|
234
|
+
|
|
235
|
+
// Boolean
|
|
180
236
|
case 'not':
|
|
181
237
|
return this._generateSelectionFromFilter(filter.filter, {
|
|
182
238
|
...context,
|
|
183
239
|
selectionInverted: !context.selectionInverted,
|
|
184
240
|
});
|
|
185
241
|
case 'and':
|
|
186
|
-
throw new QueryError('Query too complex',
|
|
242
|
+
throw new QueryError({ message: 'Query too complex', context: { query: context.originalQuery } });
|
|
187
243
|
case 'or':
|
|
188
244
|
// Optimized case
|
|
189
245
|
if (filter.filters.every(isTrivialTypenameFilter)) {
|
|
190
|
-
const typenames = filter.filters.map((
|
|
191
|
-
invariant(
|
|
192
|
-
return
|
|
246
|
+
const typenames = filter.filters.map((filter) => {
|
|
247
|
+
invariant(filter.type === 'object' && filter.typename !== null);
|
|
248
|
+
return filter.typename;
|
|
193
249
|
});
|
|
250
|
+
|
|
194
251
|
return QueryPlan.Plan.make([
|
|
195
252
|
{
|
|
196
253
|
_tag: 'SelectStep',
|
|
197
254
|
spaces: context.selectionSpaces,
|
|
255
|
+
allQueuesFromSpaces: context.selectionAllQueuesFromSpaces,
|
|
256
|
+
queues: context.selectionQueues,
|
|
198
257
|
selector: {
|
|
199
258
|
_tag: 'TypeSelector',
|
|
200
259
|
typename: typenames as DXN.String[],
|
|
@@ -202,13 +261,18 @@ export class QueryPlanner {
|
|
|
202
261
|
},
|
|
203
262
|
},
|
|
204
263
|
...this._generateDeletedHandlingSteps(context),
|
|
264
|
+
{
|
|
265
|
+
_tag: 'FilterStep',
|
|
266
|
+
filter: { ...filter },
|
|
267
|
+
},
|
|
205
268
|
]);
|
|
206
269
|
} else {
|
|
207
|
-
throw new QueryError('Query too complex',
|
|
270
|
+
throw new QueryError({ message: 'Query too complex', context: { query: context.originalQuery } });
|
|
208
271
|
}
|
|
209
272
|
|
|
210
273
|
default:
|
|
211
|
-
throw new QueryError(
|
|
274
|
+
throw new QueryError({
|
|
275
|
+
message: `Unsupported filter type: ${(filter as any).type}`,
|
|
212
276
|
context: { query: context.originalQuery },
|
|
213
277
|
});
|
|
214
278
|
}
|
|
@@ -286,7 +350,7 @@ export class QueryPlanner {
|
|
|
286
350
|
traversal: {
|
|
287
351
|
_tag: 'ReferenceTraversal',
|
|
288
352
|
direction: 'incoming',
|
|
289
|
-
property: query.property,
|
|
353
|
+
property: query.property ?? null,
|
|
290
354
|
},
|
|
291
355
|
},
|
|
292
356
|
...this._generateDeletedHandlingSteps(context),
|
|
@@ -392,6 +456,23 @@ export class QueryPlanner {
|
|
|
392
456
|
]);
|
|
393
457
|
}
|
|
394
458
|
|
|
459
|
+
private _generateHierarchyTraversalClause(
|
|
460
|
+
query: QueryAST.QueryHierarchyTraversalClause,
|
|
461
|
+
context: GenerationContext,
|
|
462
|
+
): QueryPlan.Plan {
|
|
463
|
+
return QueryPlan.Plan.make([
|
|
464
|
+
...this._generate(query.anchor, context).steps,
|
|
465
|
+
{
|
|
466
|
+
_tag: 'TraverseStep',
|
|
467
|
+
traversal: {
|
|
468
|
+
_tag: 'HierarchyTraversal',
|
|
469
|
+
direction: query.direction,
|
|
470
|
+
},
|
|
471
|
+
},
|
|
472
|
+
...this._generateDeletedHandlingSteps(context),
|
|
473
|
+
]);
|
|
474
|
+
}
|
|
475
|
+
|
|
395
476
|
/**
|
|
396
477
|
* Removes filter steps that have no predicates.
|
|
397
478
|
*/
|
|
@@ -425,6 +506,176 @@ export class QueryPlanner {
|
|
|
425
506
|
// TODO(dmaretskyi): Implement this.
|
|
426
507
|
return plan;
|
|
427
508
|
}
|
|
509
|
+
|
|
510
|
+
private _generateOrderClause(query: QueryAST.QueryOrderClause, context: GenerationContext): QueryPlan.Plan {
|
|
511
|
+
return QueryPlan.Plan.make([
|
|
512
|
+
...this._generate(query.query, context).steps,
|
|
513
|
+
{
|
|
514
|
+
_tag: 'OrderStep',
|
|
515
|
+
order: query.order,
|
|
516
|
+
},
|
|
517
|
+
]);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
private _generateLimitClause(query: QueryAST.QueryLimitClause, context: GenerationContext): QueryPlan.Plan {
|
|
521
|
+
return QueryPlan.Plan.make([
|
|
522
|
+
...this._generate(query.query, context).steps,
|
|
523
|
+
{
|
|
524
|
+
_tag: 'LimitStep',
|
|
525
|
+
limit: query.limit,
|
|
526
|
+
},
|
|
527
|
+
]);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// After complete plan is built, inspect it from the end:
|
|
531
|
+
// - Walk backwards until hitting an object set changer.
|
|
532
|
+
// - If an order step is found, skip.
|
|
533
|
+
// - Otherwise insert natural order before any limit steps (since limit should be applied after ordering).
|
|
534
|
+
// This method is recursive and also processes sub-plans in unions and set differences.
|
|
535
|
+
private _ensureOrderStep(plan: QueryPlan.Plan): QueryPlan.Plan {
|
|
536
|
+
// First, recursively process any sub-plans.
|
|
537
|
+
const processedSteps = plan.steps.map((step): QueryPlan.Step => {
|
|
538
|
+
if (step._tag === 'UnionStep') {
|
|
539
|
+
return {
|
|
540
|
+
_tag: 'UnionStep',
|
|
541
|
+
plans: step.plans.map((subPlan) => this._ensureOrderStep(subPlan)),
|
|
542
|
+
};
|
|
543
|
+
} else if (step._tag === 'SetDifferenceStep') {
|
|
544
|
+
return {
|
|
545
|
+
_tag: 'SetDifferenceStep',
|
|
546
|
+
source: this._ensureOrderStep(step.source),
|
|
547
|
+
exclude: this._ensureOrderStep(step.exclude),
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
return step;
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
const processedPlan = QueryPlan.Plan.make(processedSteps);
|
|
554
|
+
|
|
555
|
+
const OBJECT_SET_CHANGERS = new Set(['SelectStep', 'TraverseStep', 'UnionStep', 'SetDifferenceStep']);
|
|
556
|
+
for (let i = processedPlan.steps.length - 1; i >= 0; i--) {
|
|
557
|
+
const step = processedPlan.steps[i];
|
|
558
|
+
if (step._tag === 'OrderStep') {
|
|
559
|
+
return processedPlan;
|
|
560
|
+
}
|
|
561
|
+
if (OBJECT_SET_CHANGERS.has(step._tag)) {
|
|
562
|
+
break;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// Find the position to insert the order step (before any limit steps).
|
|
567
|
+
let insertIndex = processedPlan.steps.length;
|
|
568
|
+
for (let i = processedPlan.steps.length - 1; i >= 0; i--) {
|
|
569
|
+
if (processedPlan.steps[i]._tag === 'LimitStep') {
|
|
570
|
+
insertIndex = i;
|
|
571
|
+
} else {
|
|
572
|
+
break;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
const newSteps = [...processedPlan.steps];
|
|
577
|
+
newSteps.splice(insertIndex, 0, {
|
|
578
|
+
_tag: 'OrderStep',
|
|
579
|
+
order: [Order.natural.ast],
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
return QueryPlan.Plan.make(newSteps);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Propagates limits from LimitStep to SelectStep and OrderStep when possible.
|
|
587
|
+
* Limits can only be propagated if there are no unions or traversals between the LimitStep and SelectStep/OrderStep.
|
|
588
|
+
*/
|
|
589
|
+
private _optimizeLimits(plan: QueryPlan.Plan): QueryPlan.Plan {
|
|
590
|
+
// First, recursively process any sub-plans.
|
|
591
|
+
const processedSteps = plan.steps.map((step): QueryPlan.Step => {
|
|
592
|
+
if (step._tag === 'UnionStep') {
|
|
593
|
+
return {
|
|
594
|
+
_tag: 'UnionStep',
|
|
595
|
+
plans: step.plans.map((subPlan) => this._optimizeLimits(subPlan)),
|
|
596
|
+
};
|
|
597
|
+
} else if (step._tag === 'SetDifferenceStep') {
|
|
598
|
+
return {
|
|
599
|
+
_tag: 'SetDifferenceStep',
|
|
600
|
+
source: this._optimizeLimits(step.source),
|
|
601
|
+
exclude: this._optimizeLimits(step.exclude),
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
return step;
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
// Find if there's a LimitStep at the end (possibly after OrderStep).
|
|
608
|
+
let limitStepIndex = -1;
|
|
609
|
+
let limitValue: number | undefined;
|
|
610
|
+
|
|
611
|
+
for (let i = processedSteps.length - 1; i >= 0; i--) {
|
|
612
|
+
const step = processedSteps[i];
|
|
613
|
+
if (step._tag === 'LimitStep') {
|
|
614
|
+
limitStepIndex = i;
|
|
615
|
+
limitValue = step.limit;
|
|
616
|
+
break;
|
|
617
|
+
}
|
|
618
|
+
// Only allow OrderStep after LimitStep when looking backwards.
|
|
619
|
+
if (step._tag !== 'OrderStep') {
|
|
620
|
+
break;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
if (limitStepIndex === -1 || limitValue === undefined) {
|
|
625
|
+
return QueryPlan.Plan.make(processedSteps);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Check if we can propagate the limit to a SelectStep and/or OrderStep.
|
|
629
|
+
// We can only do this if there are no unions, traversals, or set differences between them.
|
|
630
|
+
const BLOCKERS = new Set(['UnionStep', 'TraverseStep', 'SetDifferenceStep']);
|
|
631
|
+
|
|
632
|
+
let selectStepIndex = -1;
|
|
633
|
+
let orderStepIndex = -1;
|
|
634
|
+
for (let i = 0; i < limitStepIndex; i++) {
|
|
635
|
+
const step = processedSteps[i];
|
|
636
|
+
if (step._tag === 'SelectStep') {
|
|
637
|
+
selectStepIndex = i;
|
|
638
|
+
}
|
|
639
|
+
if (step._tag === 'OrderStep') {
|
|
640
|
+
orderStepIndex = i;
|
|
641
|
+
}
|
|
642
|
+
if (BLOCKERS.has(step._tag)) {
|
|
643
|
+
// Found a blocker after the select/order step - can't propagate.
|
|
644
|
+
selectStepIndex = -1;
|
|
645
|
+
orderStepIndex = -1;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if (selectStepIndex === -1 && orderStepIndex === -1) {
|
|
650
|
+
return QueryPlan.Plan.make(processedSteps);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// Create a mutable copy of steps to modify.
|
|
654
|
+
const newSteps = [...processedSteps];
|
|
655
|
+
|
|
656
|
+
// Propagate the limit to the SelectStep if found.
|
|
657
|
+
if (selectStepIndex !== -1) {
|
|
658
|
+
const selectStep = newSteps[selectStepIndex] as QueryPlan.SelectStep;
|
|
659
|
+
newSteps[selectStepIndex] = {
|
|
660
|
+
...selectStep,
|
|
661
|
+
limit: limitValue,
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// Propagate the limit to the OrderStep if found.
|
|
666
|
+
if (orderStepIndex !== -1) {
|
|
667
|
+
const orderStep = newSteps[orderStepIndex] as QueryPlan.OrderStep;
|
|
668
|
+
newSteps[orderStepIndex] = {
|
|
669
|
+
...orderStep,
|
|
670
|
+
limit: limitValue,
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// Remove the LimitStep since limit is now propagated.
|
|
675
|
+
newSteps.splice(limitStepIndex, 1);
|
|
676
|
+
|
|
677
|
+
return QueryPlan.Plan.make(newSteps);
|
|
678
|
+
}
|
|
428
679
|
}
|
|
429
680
|
|
|
430
681
|
/**
|
|
@@ -441,6 +692,16 @@ type GenerationContext = {
|
|
|
441
692
|
*/
|
|
442
693
|
selectionSpaces: readonly SpaceId[];
|
|
443
694
|
|
|
695
|
+
/**
|
|
696
|
+
* Whether to select from all queues in the spaces specified by selectionSpaces.
|
|
697
|
+
*/
|
|
698
|
+
selectionAllQueuesFromSpaces: boolean;
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* Which queues to select from.
|
|
702
|
+
*/
|
|
703
|
+
selectionQueues: readonly DXN.String[];
|
|
704
|
+
|
|
444
705
|
/**
|
|
445
706
|
* How to handle deleted objects.
|
|
446
707
|
*/
|
|
@@ -455,6 +716,8 @@ type GenerationContext = {
|
|
|
455
716
|
const DEFAULT_CONTEXT: GenerationContext = {
|
|
456
717
|
originalQuery: null,
|
|
457
718
|
selectionSpaces: [],
|
|
719
|
+
selectionAllQueuesFromSpaces: false,
|
|
720
|
+
selectionQueues: [],
|
|
458
721
|
deletedHandling: 'exclude',
|
|
459
722
|
selectionInverted: false,
|
|
460
723
|
};
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { type Trigger, scheduleTask } from '@dxos/async';
|
|
6
6
|
import { Context } from '@dxos/context';
|
|
7
7
|
import { ProtocolError } from '@dxos/protocols';
|
|
8
8
|
import { schema } from '@dxos/protocols/proto';
|
|
9
9
|
import { type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
10
10
|
import {
|
|
11
11
|
type AdmissionDiscoveryService,
|
|
12
|
-
type GetAdmissionCredentialResponse,
|
|
13
12
|
type GetAdmissionCredentialRequest,
|
|
13
|
+
type GetAdmissionCredentialResponse,
|
|
14
14
|
} from '@dxos/protocols/proto/dxos/mesh/teleport';
|
|
15
15
|
import { type ExtensionContext, RpcExtension } from '@dxos/teleport';
|
|
16
16
|
|
|
@@ -81,7 +81,7 @@ export class CredentialServerExtension extends RpcExtension<
|
|
|
81
81
|
): Promise<GetAdmissionCredentialResponse> => {
|
|
82
82
|
const memberInfo = this._space.spaceState.members.get(request.memberKey);
|
|
83
83
|
if (!memberInfo?.credential) {
|
|
84
|
-
throw new ProtocolError('Space member not found.', request);
|
|
84
|
+
throw new ProtocolError({ message: 'Space member not found.', context: { ...request } });
|
|
85
85
|
}
|
|
86
86
|
return { admissionCredential: memberInfo.credential };
|
|
87
87
|
},
|
package/src/space/auth.ts
CHANGED
|
@@ -15,7 +15,7 @@ export type AuthProvider = (nonce: Uint8Array) => Promise<Uint8Array | undefined
|
|
|
15
15
|
|
|
16
16
|
export type AuthVerifier = (nonce: Uint8Array, credential: Uint8Array) => Promise<boolean>;
|
|
17
17
|
|
|
18
|
-
export type
|
|
18
|
+
export type AuthExtensionProps = {
|
|
19
19
|
provider: AuthProvider;
|
|
20
20
|
verifier: AuthVerifier;
|
|
21
21
|
onAuthSuccess: () => void;
|
|
@@ -29,7 +29,7 @@ export class AuthExtension extends RpcExtension<Services, Services> {
|
|
|
29
29
|
},
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
-
constructor(private readonly
|
|
32
|
+
constructor(private readonly _authProps: AuthExtensionProps) {
|
|
33
33
|
super({
|
|
34
34
|
requested: {
|
|
35
35
|
AuthService: schema.getService('dxos.mesh.teleport.auth.AuthService'),
|
|
@@ -46,7 +46,7 @@ export class AuthExtension extends RpcExtension<Services, Services> {
|
|
|
46
46
|
AuthService: {
|
|
47
47
|
authenticate: async ({ challenge }) => {
|
|
48
48
|
try {
|
|
49
|
-
const credential = await this.
|
|
49
|
+
const credential = await this._authProps.provider(challenge);
|
|
50
50
|
if (!credential) {
|
|
51
51
|
throw new Error('auth rejected');
|
|
52
52
|
}
|
|
@@ -67,13 +67,13 @@ export class AuthExtension extends RpcExtension<Services, Services> {
|
|
|
67
67
|
const challenge = randomBytes(32);
|
|
68
68
|
const { credential } = await this.rpc.AuthService.authenticate({ challenge });
|
|
69
69
|
invariant(credential?.length > 0, 'invalid credential');
|
|
70
|
-
const success = await this.
|
|
70
|
+
const success = await this._authProps.verifier(challenge, credential);
|
|
71
71
|
invariant(success, 'credential not verified');
|
|
72
|
-
runInContext(this._ctx, () => this.
|
|
72
|
+
runInContext(this._ctx, () => this._authProps.onAuthSuccess());
|
|
73
73
|
} catch (err) {
|
|
74
74
|
log('auth failed', err);
|
|
75
75
|
this.close();
|
|
76
|
-
this.
|
|
76
|
+
this._authProps.onAuthFailure();
|
|
77
77
|
}
|
|
78
78
|
});
|
|
79
79
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { describe, expect,
|
|
5
|
+
import { describe, expect, onTestFinished, test } from 'vitest';
|
|
6
6
|
|
|
7
7
|
import { CredentialGenerator, createCredential } from '@dxos/credentials';
|
|
8
8
|
import { FeedFactory, FeedStore } from '@dxos/feed-store';
|
|
@@ -11,13 +11,14 @@ import { type PublicKey } from '@dxos/keys';
|
|
|
11
11
|
import { log } from '@dxos/log';
|
|
12
12
|
import type { FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
|
|
13
13
|
import { AdmittedFeed } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
14
|
-
import {
|
|
14
|
+
import { StorageType, createStorage } from '@dxos/random-access-storage';
|
|
15
15
|
import { Timeframe } from '@dxos/timeframe';
|
|
16
16
|
|
|
17
|
-
import { ControlPipeline } from './control-pipeline';
|
|
18
17
|
import { valueEncoding } from '../common';
|
|
19
18
|
import { MetadataStore } from '../metadata';
|
|
20
19
|
|
|
20
|
+
import { ControlPipeline } from './control-pipeline';
|
|
21
|
+
|
|
21
22
|
describe('space/control-pipeline', () => {
|
|
22
23
|
test('admits feeds', async () => {
|
|
23
24
|
const keyring = new Keyring();
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { DeferredTask, sleepWithContext, trackLeaks } from '@dxos/async';
|
|
5
|
+
import { DeferredTask, scheduleMicroTask, sleepWithContext, trackLeaks } from '@dxos/async';
|
|
6
6
|
import { Context } from '@dxos/context';
|
|
7
7
|
import {
|
|
8
|
-
SpaceStateMachine,
|
|
9
|
-
type SpaceState,
|
|
10
|
-
type MemberInfo,
|
|
11
|
-
type FeedInfo,
|
|
12
8
|
type DelegateInvitationCredential,
|
|
9
|
+
type FeedInfo,
|
|
10
|
+
type MemberInfo,
|
|
11
|
+
type SpaceState,
|
|
12
|
+
SpaceStateMachine,
|
|
13
13
|
} from '@dxos/credentials';
|
|
14
14
|
import { type FeedWrapper } from '@dxos/feed-store';
|
|
15
15
|
import { PublicKey } from '@dxos/keys';
|
|
@@ -25,7 +25,7 @@ import { type AsyncCallback, Callback, tracer } from '@dxos/util';
|
|
|
25
25
|
import { type MetadataStore } from '../metadata';
|
|
26
26
|
import { Pipeline, type PipelineAccessor } from '../pipeline';
|
|
27
27
|
|
|
28
|
-
export type
|
|
28
|
+
export type ControlPipelineProps = {
|
|
29
29
|
spaceKey: PublicKey;
|
|
30
30
|
genesisFeed: FeedWrapper<FeedMessage>;
|
|
31
31
|
feedProvider: (feedKey: PublicKey) => Promise<FeedWrapper<FeedMessage>>;
|
|
@@ -70,7 +70,7 @@ export class ControlPipeline {
|
|
|
70
70
|
await this._saveSnapshot();
|
|
71
71
|
});
|
|
72
72
|
|
|
73
|
-
constructor({ spaceKey, genesisFeed, feedProvider, metadataStore }:
|
|
73
|
+
constructor({ spaceKey, genesisFeed, feedProvider, metadataStore }: ControlPipelineProps) {
|
|
74
74
|
this._spaceKey = spaceKey;
|
|
75
75
|
this._metadata = metadataStore;
|
|
76
76
|
this._pipeline = new Pipeline();
|
|
@@ -83,9 +83,12 @@ export class ControlPipeline {
|
|
|
83
83
|
|
|
84
84
|
// TODO(burdon): Check not stopping.
|
|
85
85
|
if (info.assertion.designation === AdmittedFeed.Designation.CONTROL && !info.key.equals(genesisFeed.key)) {
|
|
86
|
-
|
|
86
|
+
scheduleMicroTask(this._ctx, async () => {
|
|
87
87
|
try {
|
|
88
88
|
const feed = await feedProvider(info.key);
|
|
89
|
+
if (this._ctx.disposed) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
89
92
|
if (!this._pipeline.hasFeed(feed.key)) {
|
|
90
93
|
await this._pipeline.addFeed(feed);
|
|
91
94
|
}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
import { type AutomergeUrl, parseAutomergeUrl } from '@automerge/automerge-repo';
|
|
6
6
|
|
|
7
|
-
import { synchronized, trackLeaks
|
|
8
|
-
import {
|
|
7
|
+
import { Trigger, synchronized, trackLeaks } from '@dxos/async';
|
|
8
|
+
import { type DelegateInvitationCredential, type MemberInfo, getCredentialAssertion } from '@dxos/credentials';
|
|
9
9
|
import { failUndefined } from '@dxos/debug';
|
|
10
10
|
import { type FeedStore } from '@dxos/feed-store';
|
|
11
11
|
import { PublicKey } from '@dxos/keys';
|
|
@@ -19,13 +19,14 @@ import { type Teleport } from '@dxos/teleport';
|
|
|
19
19
|
import { type BlobStore } from '@dxos/teleport-extension-object-sync';
|
|
20
20
|
import { ComplexMap } from '@dxos/util';
|
|
21
21
|
|
|
22
|
+
import { createIdFromSpaceKey } from '../common/space-id';
|
|
23
|
+
import { type MetadataStore } from '../metadata';
|
|
24
|
+
|
|
22
25
|
import { CredentialRetrieverExtension } from './admission-discovery-extension';
|
|
23
26
|
import { Space } from './space';
|
|
24
27
|
import { SpaceProtocol, type SwarmIdentity } from './space-protocol';
|
|
25
|
-
import { createIdFromSpaceKey } from '../common/space-id';
|
|
26
|
-
import { type MetadataStore } from '../metadata';
|
|
27
28
|
|
|
28
|
-
export type
|
|
29
|
+
export type SpaceManagerProps = {
|
|
29
30
|
feedStore: FeedStore<FeedMessage>;
|
|
30
31
|
networkManager: SwarmNetworkManager;
|
|
31
32
|
metadataStore: MetadataStore;
|
|
@@ -35,7 +36,7 @@ export type SpaceManagerParams = {
|
|
|
35
36
|
disableP2pReplication?: boolean;
|
|
36
37
|
};
|
|
37
38
|
|
|
38
|
-
export type
|
|
39
|
+
export type ConstructSpaceProps = {
|
|
39
40
|
metadata: SpaceMetadata;
|
|
40
41
|
swarmIdentity: SwarmIdentity;
|
|
41
42
|
memberKey: PublicKey;
|
|
@@ -48,7 +49,7 @@ export type ConstructSpaceParams = {
|
|
|
48
49
|
onMemberRolesChanged: (member: MemberInfo[]) => Promise<void>;
|
|
49
50
|
};
|
|
50
51
|
|
|
51
|
-
export type
|
|
52
|
+
export type RequestSpaceAdmissionCredentialProps = {
|
|
52
53
|
spaceKey: PublicKey;
|
|
53
54
|
identityKey: PublicKey;
|
|
54
55
|
swarmIdentity: SwarmIdentity;
|
|
@@ -68,7 +69,7 @@ export class SpaceManager {
|
|
|
68
69
|
private readonly _instanceId = PublicKey.random().toHex();
|
|
69
70
|
private readonly _disableP2pReplication: boolean;
|
|
70
71
|
|
|
71
|
-
constructor({ feedStore, networkManager, metadataStore, blobStore, disableP2pReplication }:
|
|
72
|
+
constructor({ feedStore, networkManager, metadataStore, blobStore, disableP2pReplication }: SpaceManagerProps) {
|
|
72
73
|
// TODO(burdon): Assert.
|
|
73
74
|
this._feedStore = feedStore;
|
|
74
75
|
this._networkManager = networkManager;
|
|
@@ -98,7 +99,7 @@ export class SpaceManager {
|
|
|
98
99
|
onDelegatedInvitationStatusChange,
|
|
99
100
|
onMemberRolesChanged,
|
|
100
101
|
memberKey,
|
|
101
|
-
}:
|
|
102
|
+
}: ConstructSpaceProps): Promise<Space> {
|
|
102
103
|
log.trace('dxos.echo.space-manager.construct-space', trace.begin({ id: this._instanceId }));
|
|
103
104
|
log('constructing space...', { spaceKey: metadata.genesisFeedKey });
|
|
104
105
|
|
|
@@ -134,7 +135,7 @@ export class SpaceManager {
|
|
|
134
135
|
return space;
|
|
135
136
|
}
|
|
136
137
|
|
|
137
|
-
public async requestSpaceAdmissionCredential(params:
|
|
138
|
+
public async requestSpaceAdmissionCredential(params: RequestSpaceAdmissionCredentialProps): Promise<Credential> {
|
|
138
139
|
const traceKey = 'dxos.echo.space-manager.request-space-admission';
|
|
139
140
|
log.trace(traceKey, trace.begin({ id: this._instanceId }));
|
|
140
141
|
log('requesting space admission credential...', { spaceKey: params.spaceKey });
|