@peerbit/document 6.0.7-efee9d3 → 7.0.0-3a75d6e
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/benchmark/index.js +13 -14
- package/dist/benchmark/index.js.map +1 -1
- package/dist/benchmark/memory/index.d.ts +2 -0
- package/dist/benchmark/memory/index.d.ts.map +1 -0
- package/dist/benchmark/memory/index.js +122 -0
- package/dist/benchmark/memory/index.js.map +1 -0
- package/dist/benchmark/memory/insert.d.ts +2 -0
- package/dist/benchmark/memory/insert.d.ts.map +1 -0
- package/dist/benchmark/memory/insert.js +133 -0
- package/dist/benchmark/memory/insert.js.map +1 -0
- package/dist/benchmark/memory/utils.d.ts +13 -0
- package/dist/benchmark/memory/utils.d.ts.map +1 -0
- package/dist/benchmark/memory/utils.js +2 -0
- package/dist/benchmark/memory/utils.js.map +1 -0
- package/dist/benchmark/replication.js +27 -29
- package/dist/benchmark/replication.js.map +1 -1
- package/dist/src/borsh.d.ts +2 -0
- package/dist/src/borsh.d.ts.map +1 -0
- package/dist/src/borsh.js +16 -0
- package/dist/src/borsh.js.map +1 -0
- package/dist/src/index.d.ts +0 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +0 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/program.d.ts +16 -19
- package/dist/src/program.d.ts.map +1 -1
- package/dist/src/program.js +57 -68
- package/dist/src/program.js.map +1 -1
- package/dist/src/search.d.ts +46 -32
- package/dist/src/search.d.ts.map +1 -1
- package/dist/src/search.js +236 -133
- package/dist/src/search.js.map +1 -1
- package/package.json +16 -11
- package/src/borsh.ts +19 -0
- package/src/index.ts +0 -1
- package/src/program.ts +118 -118
- package/src/search.ts +438 -218
package/src/program.ts
CHANGED
|
@@ -3,36 +3,37 @@ import {
|
|
|
3
3
|
BorshError,
|
|
4
4
|
field,
|
|
5
5
|
serialize,
|
|
6
|
-
variant
|
|
6
|
+
variant,
|
|
7
7
|
} from "@dao-xyz/borsh";
|
|
8
|
-
import {
|
|
9
|
-
import { Program, type ProgramEvents } from "@peerbit/program";
|
|
8
|
+
import { CustomEvent } from "@libp2p/interface";
|
|
10
9
|
import { AccessError, DecryptedThing } from "@peerbit/crypto";
|
|
10
|
+
import * as documentsTypes from "@peerbit/document-interface";
|
|
11
|
+
import * as indexerTypes from "@peerbit/indexer-interface";
|
|
12
|
+
import {
|
|
13
|
+
type Change,
|
|
14
|
+
Entry,
|
|
15
|
+
EntryType,
|
|
16
|
+
type ShallowOrFullEntry,
|
|
17
|
+
type TrimOptions,
|
|
18
|
+
} from "@peerbit/log";
|
|
11
19
|
import { logger as loggerFn } from "@peerbit/logger";
|
|
12
|
-
import {
|
|
20
|
+
import { Program, type ProgramEvents } from "@peerbit/program";
|
|
13
21
|
import {
|
|
14
|
-
type
|
|
15
|
-
Observer,
|
|
16
|
-
Replicator,
|
|
22
|
+
type SharedAppendOptions,
|
|
17
23
|
SharedLog,
|
|
18
24
|
type SharedLogOptions,
|
|
19
|
-
type SharedAppendOptions
|
|
20
25
|
} from "@peerbit/shared-log";
|
|
21
|
-
import
|
|
22
|
-
|
|
23
|
-
export type { RoleOptions }; // For convenience (so that consumers does not have to do the import above from shared-log packages)
|
|
24
|
-
|
|
26
|
+
import { MAX_BATCH_SIZE } from "./constants.js";
|
|
25
27
|
import {
|
|
26
|
-
type IndexableFields,
|
|
27
28
|
BORSH_ENCODING_OPERATION,
|
|
29
|
+
type CanRead,
|
|
30
|
+
type CanSearch,
|
|
28
31
|
DeleteOperation,
|
|
29
32
|
DocumentIndex,
|
|
30
33
|
Operation,
|
|
31
34
|
PutOperation,
|
|
32
|
-
type
|
|
33
|
-
type CanRead
|
|
35
|
+
type TransformOptions,
|
|
34
36
|
} from "./search.js";
|
|
35
|
-
import { MAX_BATCH_SIZE } from "./constants.js";
|
|
36
37
|
|
|
37
38
|
const logger = loggerFn({ module: "document" });
|
|
38
39
|
|
|
@@ -66,30 +67,29 @@ type CanPerformDelete<T> = {
|
|
|
66
67
|
|
|
67
68
|
export type CanPerformOperations<T> = CanPerformPut<T> | CanPerformDelete<T>;
|
|
68
69
|
export type CanPerform<T> = (
|
|
69
|
-
properties: CanPerformOperations<T
|
|
70
|
+
properties: CanPerformOperations<T>,
|
|
70
71
|
) => MaybePromise<boolean>;
|
|
71
72
|
|
|
72
|
-
export type SetupOptions<T> = {
|
|
73
|
+
export type SetupOptions<T, I = T> = {
|
|
73
74
|
type: AbstractType<T>;
|
|
74
75
|
canOpen?: (program: T) => MaybePromise<boolean>;
|
|
75
76
|
canPerform?: CanPerform<T>;
|
|
76
|
-
id?: (obj: any) =>
|
|
77
|
+
id?: (obj: any) => indexerTypes.IdPrimitive;
|
|
77
78
|
index?: {
|
|
78
|
-
idProperty?: string | string[];
|
|
79
79
|
canSearch?: CanSearch;
|
|
80
80
|
canRead?: CanRead<T>;
|
|
81
|
-
|
|
82
|
-
}
|
|
81
|
+
idProperty?: string | string[];
|
|
82
|
+
} & TransformOptions<T, I>;
|
|
83
83
|
log?: {
|
|
84
84
|
trim?: TrimOptions;
|
|
85
85
|
};
|
|
86
86
|
} & SharedLogOptions<Operation>;
|
|
87
87
|
|
|
88
88
|
@variant("documents")
|
|
89
|
-
export class Documents<
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
> {
|
|
89
|
+
export class Documents<
|
|
90
|
+
T,
|
|
91
|
+
I extends Record<string, any> = T extends Record<string, any> ? T : any,
|
|
92
|
+
> extends Program<SetupOptions<T, I>, DocumentEvents<T> & ProgramEvents> {
|
|
93
93
|
@field({ type: SharedLog })
|
|
94
94
|
log: SharedLog<Operation>;
|
|
95
95
|
|
|
@@ -97,20 +97,20 @@ export class Documents<T> extends Program<
|
|
|
97
97
|
immutable: boolean; // "Can I overwrite a document?"
|
|
98
98
|
|
|
99
99
|
@field({ type: DocumentIndex })
|
|
100
|
-
private _index: DocumentIndex<T>;
|
|
100
|
+
private _index: DocumentIndex<T, I>;
|
|
101
101
|
|
|
102
|
-
private _clazz
|
|
102
|
+
private _clazz!: AbstractType<T>;
|
|
103
103
|
|
|
104
104
|
private _optionCanPerform?: CanPerform<T>;
|
|
105
|
-
private _manuallySynced
|
|
106
|
-
private idResolver
|
|
105
|
+
private _manuallySynced!: Set<string>;
|
|
106
|
+
private idResolver!: (any: any) => indexerTypes.IdPrimitive;
|
|
107
107
|
|
|
108
108
|
canOpen?: (program: T, entry: Entry<Operation>) => Promise<boolean> | boolean;
|
|
109
109
|
|
|
110
110
|
constructor(properties?: {
|
|
111
111
|
id?: Uint8Array;
|
|
112
112
|
immutable?: boolean;
|
|
113
|
-
index?: DocumentIndex<T>;
|
|
113
|
+
index?: DocumentIndex<T, I>;
|
|
114
114
|
}) {
|
|
115
115
|
super();
|
|
116
116
|
|
|
@@ -119,11 +119,11 @@ export class Documents<T> extends Program<
|
|
|
119
119
|
this._index = properties?.index || new DocumentIndex();
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
get index(): DocumentIndex<T> {
|
|
122
|
+
get index(): DocumentIndex<T, I> {
|
|
123
123
|
return this._index;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
async open(options: SetupOptions<T>) {
|
|
126
|
+
async open(options: SetupOptions<T, I>) {
|
|
127
127
|
this._clazz = options.type;
|
|
128
128
|
this.canOpen = options.canOpen;
|
|
129
129
|
|
|
@@ -131,7 +131,7 @@ export class Documents<T> extends Program<
|
|
|
131
131
|
if (Program.isPrototypeOf(this._clazz)) {
|
|
132
132
|
if (!this.canOpen) {
|
|
133
133
|
throw new Error(
|
|
134
|
-
"Document store needs to be opened with canOpen option when the document type is a Program"
|
|
134
|
+
"Document store needs to be opened with canOpen option when the document type is a Program",
|
|
135
135
|
);
|
|
136
136
|
}
|
|
137
137
|
}
|
|
@@ -143,28 +143,19 @@ export class Documents<T> extends Program<
|
|
|
143
143
|
options.id ||
|
|
144
144
|
(typeof idProperty === "string"
|
|
145
145
|
? (obj: any) => obj[idProperty as string]
|
|
146
|
-
: (obj: any) =>
|
|
146
|
+
: (obj: any) =>
|
|
147
|
+
indexerTypes.extractFieldValue(obj, idProperty as string[]));
|
|
147
148
|
|
|
148
149
|
this.idResolver = idResolver;
|
|
149
150
|
|
|
150
|
-
let transform: IndexableFields<T>;
|
|
151
|
-
if (options.index?.fields) {
|
|
152
|
-
if (typeof options.index.fields === "function") {
|
|
153
|
-
transform = options.index.fields;
|
|
154
|
-
} else {
|
|
155
|
-
transform = options.index.fields;
|
|
156
|
-
}
|
|
157
|
-
} else {
|
|
158
|
-
transform = (obj) => obj as Record<string, any>; // TODO check types
|
|
159
|
-
}
|
|
160
151
|
await this._index.open({
|
|
161
|
-
type: this._clazz,
|
|
162
152
|
log: this.log,
|
|
163
153
|
canRead: options?.index?.canRead,
|
|
164
154
|
canSearch: options.index?.canSearch,
|
|
165
|
-
|
|
155
|
+
documentType: this._clazz,
|
|
156
|
+
transform: options.index,
|
|
166
157
|
indexBy: idProperty,
|
|
167
|
-
sync: async (result:
|
|
158
|
+
sync: async (result: documentsTypes.Results<T>) => {
|
|
168
159
|
// here we arrive for all the results we want to persist.
|
|
169
160
|
// we we need to do here is
|
|
170
161
|
// 1. add the entry to a list of entries that we should persist through prunes
|
|
@@ -175,7 +166,7 @@ export class Documents<T> extends Program<
|
|
|
175
166
|
}
|
|
176
167
|
return this.log.log.join(heads);
|
|
177
168
|
},
|
|
178
|
-
dbType: this.constructor
|
|
169
|
+
dbType: this.constructor,
|
|
179
170
|
});
|
|
180
171
|
|
|
181
172
|
await this.log.open({
|
|
@@ -184,13 +175,13 @@ export class Documents<T> extends Program<
|
|
|
184
175
|
canAppend: this.canAppend.bind(this),
|
|
185
176
|
onChange: this.handleChanges.bind(this),
|
|
186
177
|
trim: options?.log?.trim,
|
|
187
|
-
|
|
178
|
+
replicate: options?.replicate,
|
|
188
179
|
replicas: options?.replicas,
|
|
189
180
|
sync: (entry: any) => {
|
|
190
181
|
// here we arrive when ever a insertion/pruning behaviour processes an entry
|
|
191
182
|
// returning true means that it should persist
|
|
192
183
|
return this._manuallySynced.has(entry.gid);
|
|
193
|
-
}
|
|
184
|
+
},
|
|
194
185
|
});
|
|
195
186
|
}
|
|
196
187
|
|
|
@@ -201,20 +192,13 @@ export class Documents<T> extends Program<
|
|
|
201
192
|
private async _resolveEntry(history: Entry<Operation> | string) {
|
|
202
193
|
return typeof history === "string"
|
|
203
194
|
? (await this.log.log.get(history)) ||
|
|
204
|
-
|
|
195
|
+
(await Entry.fromMultihash<Operation>(this.log.log.blocks, history))
|
|
205
196
|
: history;
|
|
206
197
|
}
|
|
207
198
|
|
|
208
|
-
async updateRole(role: RoleOptions) {
|
|
209
|
-
await this.log.updateRole(role);
|
|
210
|
-
}
|
|
211
|
-
get role(): Replicator | Observer {
|
|
212
|
-
return this.log.role;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
199
|
async canAppend(
|
|
216
200
|
entry: Entry<Operation>,
|
|
217
|
-
reference?: { document: T; operation: PutOperation }
|
|
201
|
+
reference?: { document: T; operation: PutOperation },
|
|
218
202
|
): Promise<boolean> {
|
|
219
203
|
const l0 = await this._canAppend(entry as Entry<Operation>, reference);
|
|
220
204
|
if (!l0) {
|
|
@@ -244,16 +228,16 @@ export class Documents<T> extends Program<
|
|
|
244
228
|
!(await this._optionCanPerform(
|
|
245
229
|
operation instanceof PutOperation
|
|
246
230
|
? {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
231
|
+
type: "put",
|
|
232
|
+
value: document!,
|
|
233
|
+
operation,
|
|
234
|
+
entry: entry as any as Entry<PutOperation>,
|
|
235
|
+
}
|
|
252
236
|
: {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
237
|
+
type: "delete",
|
|
238
|
+
operation,
|
|
239
|
+
entry: entry as any as Entry<DeleteOperation>,
|
|
240
|
+
},
|
|
257
241
|
))
|
|
258
242
|
) {
|
|
259
243
|
return false;
|
|
@@ -272,12 +256,12 @@ export class Documents<T> extends Program<
|
|
|
272
256
|
|
|
273
257
|
async _canAppend(
|
|
274
258
|
entry: Entry<Operation>,
|
|
275
|
-
reference?: { document: T; operation: PutOperation }
|
|
259
|
+
reference?: { document: T; operation: PutOperation },
|
|
276
260
|
): Promise<PutOperation | DeleteOperation | false> {
|
|
277
261
|
const resolve = async (history: Entry<Operation> | string) => {
|
|
278
262
|
return typeof history === "string"
|
|
279
263
|
? this.log.log.get(history) ||
|
|
280
|
-
|
|
264
|
+
(await Entry.fromMultihash(this.log.log.blocks, history))
|
|
281
265
|
: history;
|
|
282
266
|
};
|
|
283
267
|
const pointsToHistory = async (history: Entry<Operation> | string) => {
|
|
@@ -301,7 +285,7 @@ export class Documents<T> extends Program<
|
|
|
301
285
|
try {
|
|
302
286
|
entry.init({
|
|
303
287
|
encoding: this.log.log.encoding,
|
|
304
|
-
keychain: this.node.services.keychain
|
|
288
|
+
keychain: this.node.services.keychain,
|
|
305
289
|
});
|
|
306
290
|
const operation =
|
|
307
291
|
reference?.operation || entry._payload instanceof DecryptedThing
|
|
@@ -315,9 +299,10 @@ export class Documents<T> extends Program<
|
|
|
315
299
|
this.index.valueEncoding.decoder(putOperation.data);
|
|
316
300
|
const keyValue = this.idResolver(value);
|
|
317
301
|
|
|
318
|
-
const key =
|
|
302
|
+
const key = indexerTypes.toId(keyValue);
|
|
319
303
|
|
|
320
|
-
const existingDocument = await this.index.
|
|
304
|
+
const existingDocument = (await this.index.getDetailed(key))?.[0]
|
|
305
|
+
?.results[0];
|
|
321
306
|
if (existingDocument && existingDocument.context.head !== entry.hash) {
|
|
322
307
|
// econd condition can false if we reset the operation log, while not resetting the index. For example when doing .recover
|
|
323
308
|
if (this.immutable) {
|
|
@@ -344,7 +329,9 @@ export class Documents<T> extends Program<
|
|
|
344
329
|
if (entry.next.length !== 1) {
|
|
345
330
|
return false;
|
|
346
331
|
}
|
|
347
|
-
const existingDocument =
|
|
332
|
+
const existingDocument = (
|
|
333
|
+
await this.index.getDetailed(operation.key)
|
|
334
|
+
)?.[0].results[0];
|
|
348
335
|
if (!existingDocument) {
|
|
349
336
|
// already deleted
|
|
350
337
|
return operation; // assume ok
|
|
@@ -377,32 +364,33 @@ export class Documents<T> extends Program<
|
|
|
377
364
|
|
|
378
365
|
public async put(
|
|
379
366
|
doc: T,
|
|
380
|
-
options?: SharedAppendOptions<Operation> & { unique?: boolean }
|
|
367
|
+
options?: SharedAppendOptions<Operation> & { unique?: boolean },
|
|
381
368
|
) {
|
|
382
369
|
const keyValue = this.idResolver(doc);
|
|
383
370
|
|
|
384
371
|
// type check the key
|
|
385
|
-
|
|
372
|
+
indexerTypes.checkId(keyValue);
|
|
386
373
|
|
|
387
374
|
const ser = serialize(doc);
|
|
388
375
|
if (ser.length > MAX_BATCH_SIZE) {
|
|
389
376
|
throw new Error(
|
|
390
|
-
`Document is too large (${
|
|
391
|
-
|
|
377
|
+
`Document is too large (${
|
|
378
|
+
ser.length * 1e-6
|
|
379
|
+
}) mb). Needs to be less than ${MAX_BATCH_SIZE * 1e-6} mb`,
|
|
392
380
|
);
|
|
393
381
|
}
|
|
394
382
|
|
|
395
383
|
const existingDocument = options?.unique
|
|
396
384
|
? undefined
|
|
397
385
|
: (
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
386
|
+
await this._index.getDetailed(keyValue, {
|
|
387
|
+
local: true,
|
|
388
|
+
remote: { sync: true }, // only query remote if we know they exist
|
|
389
|
+
})
|
|
390
|
+
)?.[0]?.results[0];
|
|
403
391
|
|
|
404
392
|
const operation = new PutOperation({
|
|
405
|
-
data: ser
|
|
393
|
+
data: ser,
|
|
406
394
|
});
|
|
407
395
|
const appended = await this.log.append(operation, {
|
|
408
396
|
...options,
|
|
@@ -410,73 +398,86 @@ export class Documents<T> extends Program<
|
|
|
410
398
|
next: existingDocument
|
|
411
399
|
? [await this._resolveEntry(existingDocument.context.head)]
|
|
412
400
|
: [],
|
|
413
|
-
...options?.meta
|
|
401
|
+
...options?.meta,
|
|
414
402
|
},
|
|
415
403
|
canAppend: (entry) => {
|
|
416
404
|
return this.canAppend(entry, { document: doc, operation });
|
|
417
405
|
},
|
|
418
406
|
onChange: (change) => {
|
|
419
407
|
return this.handleChanges(change, { document: doc, operation });
|
|
420
|
-
}
|
|
408
|
+
},
|
|
421
409
|
});
|
|
422
410
|
|
|
423
411
|
return appended;
|
|
424
412
|
}
|
|
425
413
|
|
|
426
|
-
async del(
|
|
427
|
-
|
|
414
|
+
async del(
|
|
415
|
+
id: indexerTypes.Ideable,
|
|
416
|
+
options?: SharedAppendOptions<Operation>,
|
|
417
|
+
) {
|
|
418
|
+
const key = indexerTypes.toId(id);
|
|
428
419
|
const existing = (
|
|
429
420
|
await this._index.getDetailed(key, {
|
|
430
421
|
local: true,
|
|
431
|
-
remote: { sync: true }
|
|
422
|
+
remote: { sync: true },
|
|
432
423
|
})
|
|
433
424
|
)?.[0]?.results[0];
|
|
434
425
|
|
|
435
426
|
if (!existing) {
|
|
436
|
-
throw new Error(`No entry with key '${key}' in the database`);
|
|
427
|
+
throw new Error(`No entry with key '${key.primitive}' in the database`);
|
|
437
428
|
}
|
|
438
429
|
|
|
439
430
|
return this.log.append(
|
|
440
431
|
new DeleteOperation({
|
|
441
|
-
key
|
|
432
|
+
key,
|
|
442
433
|
}),
|
|
443
434
|
{
|
|
444
435
|
...options,
|
|
445
436
|
meta: {
|
|
446
437
|
next: [await this._resolveEntry(existing.context.head)],
|
|
447
438
|
type: EntryType.CUT,
|
|
448
|
-
...options?.meta
|
|
449
|
-
}
|
|
450
|
-
} //
|
|
439
|
+
...options?.meta,
|
|
440
|
+
},
|
|
441
|
+
}, //
|
|
451
442
|
);
|
|
452
443
|
}
|
|
453
444
|
|
|
454
445
|
async handleChanges(
|
|
455
446
|
change: Change<Operation>,
|
|
456
|
-
reference?: { document: T; operation: PutOperation }
|
|
447
|
+
reference?: { document: T; operation: PutOperation },
|
|
457
448
|
): Promise<void> {
|
|
458
449
|
const isAppendOperation =
|
|
459
450
|
change?.added.length === 1 ? !!change.added[0] : false;
|
|
460
451
|
|
|
461
|
-
const
|
|
462
|
-
const
|
|
463
|
-
for (const r of removed) {
|
|
452
|
+
const removedSet = new Map<string, ShallowOrFullEntry<Operation>>();
|
|
453
|
+
for (const r of change.removed) {
|
|
464
454
|
removedSet.set(r.hash, r);
|
|
465
455
|
}
|
|
466
|
-
const sortedEntries = [
|
|
467
|
-
.
|
|
468
|
-
.
|
|
456
|
+
const sortedEntries = [
|
|
457
|
+
...change.added,
|
|
458
|
+
...((await Promise.all(
|
|
459
|
+
change.removed.map((x) =>
|
|
460
|
+
x instanceof Entry ? x : this.log.log.entryIndex.get(x.hash),
|
|
461
|
+
),
|
|
462
|
+
)) || []),
|
|
463
|
+
]; // TODO assert sorting
|
|
464
|
+
/*
|
|
465
|
+
const sortedEntries = [...change.added, ...(removed || [])]
|
|
466
|
+
.sort(this.log.log.sortFn)
|
|
467
|
+
.reverse(); // sort so we get newest to oldest */
|
|
469
468
|
|
|
470
469
|
// There might be a case where change.added and change.removed contains the same document id. Usaully because you use the "trim" option
|
|
471
470
|
// in combination with inserting the same document. To mitigate this, we loop through the changes and modify the behaviour for this
|
|
472
471
|
|
|
473
472
|
let documentsChanged: DocumentsChange<T> = {
|
|
474
473
|
added: [],
|
|
475
|
-
removed: []
|
|
474
|
+
removed: [],
|
|
476
475
|
};
|
|
477
476
|
|
|
478
477
|
let modified: Set<string | number | bigint> = new Set();
|
|
479
478
|
for (const item of sortedEntries) {
|
|
479
|
+
if (!item) continue;
|
|
480
|
+
|
|
480
481
|
try {
|
|
481
482
|
const payload =
|
|
482
483
|
item._payload instanceof DecryptedThing
|
|
@@ -493,7 +494,7 @@ export class Documents<T> extends Program<
|
|
|
493
494
|
// get index key from value
|
|
494
495
|
const keyObject = this.idResolver(value);
|
|
495
496
|
|
|
496
|
-
const key =
|
|
497
|
+
const key = indexerTypes.toId(keyObject);
|
|
497
498
|
|
|
498
499
|
// document is already updated with more recent entry
|
|
499
500
|
if (modified.has(key.primitive)) {
|
|
@@ -505,17 +506,16 @@ export class Documents<T> extends Program<
|
|
|
505
506
|
// if replicator, then open
|
|
506
507
|
if (
|
|
507
508
|
(await this.canOpen!(value, item)) &&
|
|
508
|
-
this.log.
|
|
509
|
-
(await this.log.replicator(item)) // TODO types, throw runtime error if replicator is not provided
|
|
509
|
+
(await this.log.isReplicator(item)) // TODO types, throw runtime error if replicator is not provided
|
|
510
510
|
) {
|
|
511
511
|
value = (await this.node.open(value, {
|
|
512
512
|
parent: this as Program<any, any>,
|
|
513
|
-
existing: "reuse"
|
|
513
|
+
existing: "reuse",
|
|
514
514
|
})) as any as T; // TODO types
|
|
515
515
|
}
|
|
516
516
|
}
|
|
517
517
|
documentsChanged.added.push(value);
|
|
518
|
-
this._index.put(value, item, key);
|
|
518
|
+
await this._index.put(value, item, key);
|
|
519
519
|
modified.add(key.primitive);
|
|
520
520
|
} else if (
|
|
521
521
|
(payload instanceof DeleteOperation && !removedSet.has(item.hash)) ||
|
|
@@ -525,24 +525,24 @@ export class Documents<T> extends Program<
|
|
|
525
525
|
this._manuallySynced.delete(item.gid);
|
|
526
526
|
|
|
527
527
|
let value: T;
|
|
528
|
-
let key:
|
|
528
|
+
let key: indexerTypes.IdKey;
|
|
529
529
|
|
|
530
530
|
if (payload instanceof PutOperation) {
|
|
531
531
|
value = this.index.valueEncoding.decoder(payload.data);
|
|
532
|
-
key =
|
|
532
|
+
key = indexerTypes.toId(this.idResolver(value));
|
|
533
533
|
// document is already updated with more recent entry
|
|
534
|
-
if (modified.has(key)) {
|
|
534
|
+
if (modified.has(key.primitive)) {
|
|
535
535
|
continue;
|
|
536
536
|
}
|
|
537
537
|
} else if (payload instanceof DeleteOperation) {
|
|
538
|
-
key = payload.key
|
|
538
|
+
key = payload.key;
|
|
539
539
|
// document is already updated with more recent entry
|
|
540
|
-
if (modified.has(key)) {
|
|
540
|
+
if (modified.has(key.primitive)) {
|
|
541
541
|
continue;
|
|
542
542
|
}
|
|
543
543
|
const document = await this._index.get(key, {
|
|
544
544
|
local: true,
|
|
545
|
-
remote: false
|
|
545
|
+
remote: false,
|
|
546
546
|
});
|
|
547
547
|
if (!document) {
|
|
548
548
|
continue;
|
|
@@ -559,11 +559,11 @@ export class Documents<T> extends Program<
|
|
|
559
559
|
}
|
|
560
560
|
|
|
561
561
|
// update index
|
|
562
|
-
this._index.del(key);
|
|
563
|
-
|
|
564
|
-
modified.add(key);
|
|
562
|
+
await this._index.del(key);
|
|
563
|
+
modified.add(key.primitive);
|
|
565
564
|
} else {
|
|
566
565
|
// Unknown operation
|
|
566
|
+
throw new OperationError("Unknown operation");
|
|
567
567
|
}
|
|
568
568
|
} catch (error) {
|
|
569
569
|
if (error instanceof AccessError) {
|
|
@@ -574,7 +574,7 @@ export class Documents<T> extends Program<
|
|
|
574
574
|
}
|
|
575
575
|
|
|
576
576
|
this.events.dispatchEvent(
|
|
577
|
-
new CustomEvent("change", { detail: documentsChanged })
|
|
577
|
+
new CustomEvent("change", { detail: documentsChanged }),
|
|
578
578
|
);
|
|
579
579
|
}
|
|
580
580
|
}
|