document-drive 1.3.3 → 1.4.0
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/package.json +20 -14
- package/src/server/index.ts +140 -140
- package/src/server/listener/transmitter/internal.ts +4 -0
- package/src/server/types.ts +22 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "document-drive",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./src/index.ts",
|
|
@@ -26,34 +26,32 @@
|
|
|
26
26
|
"./src"
|
|
27
27
|
],
|
|
28
28
|
"peerDependencies": {
|
|
29
|
+
"@powerhousedao/scalars": "latest",
|
|
30
|
+
"change-case": "^5.4.4",
|
|
29
31
|
"document-model": "^2.3.1",
|
|
30
32
|
"document-model-libs": "^1.104.0",
|
|
31
|
-
"
|
|
33
|
+
"graphql": "^16.9.0",
|
|
34
|
+
"graphql-request": "^6.1.0",
|
|
35
|
+
"json-stringify-deterministic": "^1.0.12",
|
|
36
|
+
"nanoevents": "^9.0.0",
|
|
37
|
+
"sanitize-filename": "^1.6.3",
|
|
38
|
+
"uuid": "^9.0.1"
|
|
32
39
|
},
|
|
33
40
|
"optionalDependencies": {
|
|
34
41
|
"@prisma/client": "^5.18.0",
|
|
42
|
+
"exponential-backoff": "^3.1.1",
|
|
35
43
|
"localforage": "^1.10.0",
|
|
36
44
|
"redis": "^4.6.15",
|
|
37
45
|
"sequelize": "^6.37.3",
|
|
38
46
|
"sqlite3": "^5.1.7"
|
|
39
47
|
},
|
|
40
|
-
"dependencies": {
|
|
41
|
-
"change-case": "^5.4.4",
|
|
42
|
-
"exponential-backoff": "^3.1.1",
|
|
43
|
-
"graphql": "^16.9.0",
|
|
44
|
-
"graphql-request": "^6.1.0",
|
|
45
|
-
"json-stringify-deterministic": "^1.0.12",
|
|
46
|
-
"nanoevents": "^9.0.0",
|
|
47
|
-
"sanitize-filename": "^1.6.3",
|
|
48
|
-
"uuid": "^9.0.1"
|
|
49
|
-
},
|
|
50
48
|
"devDependencies": {
|
|
51
49
|
"@powerhousedao/scalars": "latest",
|
|
52
50
|
"@prisma/client": "5.17.0",
|
|
53
51
|
"@types/node": "^20.14.11",
|
|
54
52
|
"@types/uuid": "^9.0.8",
|
|
55
53
|
"document-model": "^2.6.0",
|
|
56
|
-
"document-model-libs": "^1.
|
|
54
|
+
"document-model-libs": "^1.110.1",
|
|
57
55
|
"fake-indexeddb": "^5.0.2",
|
|
58
56
|
"localforage": "^1.10.0",
|
|
59
57
|
"msw": "^2.3.1",
|
|
@@ -61,7 +59,15 @@
|
|
|
61
59
|
"sequelize": "^6.37.2",
|
|
62
60
|
"sqlite3": "^5.1.7",
|
|
63
61
|
"webdriverio": "^9.0.9",
|
|
64
|
-
"vitest-fetch-mock": "^0.3.0"
|
|
62
|
+
"vitest-fetch-mock": "^0.3.0",
|
|
63
|
+
"change-case": "^5.4.4",
|
|
64
|
+
"exponential-backoff": "^3.1.1",
|
|
65
|
+
"graphql": "^16.9.0",
|
|
66
|
+
"graphql-request": "^6.1.0",
|
|
67
|
+
"json-stringify-deterministic": "^1.0.12",
|
|
68
|
+
"nanoevents": "^9.0.0",
|
|
69
|
+
"sanitize-filename": "^1.6.3",
|
|
70
|
+
"uuid": "^9.0.1"
|
|
65
71
|
},
|
|
66
72
|
"scripts": {
|
|
67
73
|
"check-types": "tsc --noEmit",
|
package/src/server/index.ts
CHANGED
|
@@ -136,7 +136,7 @@ export class BaseDocumentDriveServer
|
|
|
136
136
|
storage: IDriveStorage = new MemoryStorage(),
|
|
137
137
|
cache: ICache = new InMemoryCache(),
|
|
138
138
|
queueManager: IQueueManager = new BaseQueueManager(),
|
|
139
|
-
options?: DocumentDriveServerOptions
|
|
139
|
+
options?: DocumentDriveServerOptions,
|
|
140
140
|
) {
|
|
141
141
|
super();
|
|
142
142
|
this.options = {
|
|
@@ -157,7 +157,7 @@ export class BaseDocumentDriveServer
|
|
|
157
157
|
this.listenerStateManager = new ListenerManager(
|
|
158
158
|
this,
|
|
159
159
|
undefined,
|
|
160
|
-
options?.listenerManager
|
|
160
|
+
options?.listenerManager,
|
|
161
161
|
);
|
|
162
162
|
this.documentModels = documentModels;
|
|
163
163
|
this.storage = storage;
|
|
@@ -166,7 +166,7 @@ export class BaseDocumentDriveServer
|
|
|
166
166
|
this.defaultDrivesManager = new DefaultDrivesManager(
|
|
167
167
|
this,
|
|
168
168
|
this.defaultDrivesManagerDelegate,
|
|
169
|
-
options
|
|
169
|
+
options,
|
|
170
170
|
);
|
|
171
171
|
|
|
172
172
|
this.storage.setStorageDelegate?.({
|
|
@@ -210,7 +210,7 @@ export class BaseDocumentDriveServer
|
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
private getCombinedSyncUnitStatus(
|
|
213
|
-
syncUnitStatus: SyncUnitStatusObject
|
|
213
|
+
syncUnitStatus: SyncUnitStatusObject,
|
|
214
214
|
): SyncStatus {
|
|
215
215
|
if (!syncUnitStatus.pull && !syncUnitStatus.push) return "INITIAL_SYNC";
|
|
216
216
|
if (syncUnitStatus.pull === "INITIAL_SYNC") return "INITIAL_SYNC";
|
|
@@ -225,7 +225,7 @@ export class BaseDocumentDriveServer
|
|
|
225
225
|
"SUCCESS",
|
|
226
226
|
];
|
|
227
227
|
const sortedStatus = Object.values(syncUnitStatus).sort(
|
|
228
|
-
(a, b) => order.indexOf(a) - order.indexOf(b)
|
|
228
|
+
(a, b) => order.indexOf(a) - order.indexOf(b),
|
|
229
229
|
);
|
|
230
230
|
|
|
231
231
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
@@ -234,10 +234,10 @@ export class BaseDocumentDriveServer
|
|
|
234
234
|
|
|
235
235
|
private initSyncStatus(
|
|
236
236
|
syncUnitId: string,
|
|
237
|
-
status: Partial<SyncUnitStatusObject
|
|
237
|
+
status: Partial<SyncUnitStatusObject>,
|
|
238
238
|
) {
|
|
239
239
|
const defaultSyncUnitStatus: SyncUnitStatusObject = Object.entries(
|
|
240
|
-
status
|
|
240
|
+
status,
|
|
241
241
|
).reduce((acc, [key, _status]) => {
|
|
242
242
|
return {
|
|
243
243
|
...acc,
|
|
@@ -251,13 +251,13 @@ export class BaseDocumentDriveServer
|
|
|
251
251
|
syncUnitId,
|
|
252
252
|
this.getCombinedSyncUnitStatus(defaultSyncUnitStatus),
|
|
253
253
|
undefined,
|
|
254
|
-
defaultSyncUnitStatus
|
|
254
|
+
defaultSyncUnitStatus,
|
|
255
255
|
);
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
private async initializeDriveSyncStatus(
|
|
259
259
|
driveId: string,
|
|
260
|
-
drive: DocumentDriveDocument
|
|
260
|
+
drive: DocumentDriveDocument,
|
|
261
261
|
) {
|
|
262
262
|
const syncUnits = await this.getSynchronizationUnitsIds(driveId);
|
|
263
263
|
const syncStatus: SyncUnitStatusObject = {
|
|
@@ -277,7 +277,7 @@ export class BaseDocumentDriveServer
|
|
|
277
277
|
private updateSyncUnitStatus(
|
|
278
278
|
syncUnitId: string,
|
|
279
279
|
status: Partial<SyncUnitStatusObject> | null,
|
|
280
|
-
error?: Error
|
|
280
|
+
error?: Error,
|
|
281
281
|
) {
|
|
282
282
|
if (status === null) {
|
|
283
283
|
this.syncStatus.delete(syncUnitId);
|
|
@@ -293,7 +293,7 @@ export class BaseDocumentDriveServer
|
|
|
293
293
|
|
|
294
294
|
const shouldUpdateStatus = Object.entries(status).some(
|
|
295
295
|
([key, _status]) =>
|
|
296
|
-
syncUnitStatus[key as keyof SyncUnitStatusObject] !== _status
|
|
296
|
+
syncUnitStatus[key as keyof SyncUnitStatusObject] !== _status,
|
|
297
297
|
);
|
|
298
298
|
|
|
299
299
|
if (shouldUpdateStatus) {
|
|
@@ -321,7 +321,7 @@ export class BaseDocumentDriveServer
|
|
|
321
321
|
syncUnitId,
|
|
322
322
|
this.getCombinedSyncUnitStatus(newstatus),
|
|
323
323
|
error,
|
|
324
|
-
newstatus
|
|
324
|
+
newstatus,
|
|
325
325
|
);
|
|
326
326
|
}
|
|
327
327
|
}
|
|
@@ -338,7 +338,7 @@ export class BaseDocumentDriveServer
|
|
|
338
338
|
? this.queueDriveOperations(
|
|
339
339
|
strand.driveId,
|
|
340
340
|
operations as Operation<DocumentDriveAction | BaseAction>[],
|
|
341
|
-
{ source }
|
|
341
|
+
{ source },
|
|
342
342
|
)
|
|
343
343
|
: this.queueOperations(strand.driveId, strand.documentId, operations, {
|
|
344
344
|
source,
|
|
@@ -352,7 +352,7 @@ export class BaseDocumentDriveServer
|
|
|
352
352
|
strand.driveId,
|
|
353
353
|
[strand.documentId],
|
|
354
354
|
[strand.scope],
|
|
355
|
-
[strand.branch]
|
|
355
|
+
[strand.branch],
|
|
356
356
|
)
|
|
357
357
|
).map((s) => s.syncId)
|
|
358
358
|
: [strand.driveId];
|
|
@@ -363,7 +363,7 @@ export class BaseDocumentDriveServer
|
|
|
363
363
|
this.updateSyncUnitStatus(
|
|
364
364
|
syncUnit,
|
|
365
365
|
{ [operationSource]: result.status },
|
|
366
|
-
result.error
|
|
366
|
+
result.error,
|
|
367
367
|
);
|
|
368
368
|
}
|
|
369
369
|
}
|
|
@@ -374,11 +374,11 @@ export class BaseDocumentDriveServer
|
|
|
374
374
|
private handleListenerError(
|
|
375
375
|
error: Error,
|
|
376
376
|
driveId: string,
|
|
377
|
-
listener: ListenerState
|
|
377
|
+
listener: ListenerState,
|
|
378
378
|
) {
|
|
379
379
|
logger.error(
|
|
380
380
|
`Listener ${listener.listener.label ?? listener.listener.listenerId} error:`,
|
|
381
|
-
error
|
|
381
|
+
error,
|
|
382
382
|
);
|
|
383
383
|
|
|
384
384
|
const status = error instanceof OperationError ? error.status : "ERROR";
|
|
@@ -403,7 +403,7 @@ export class BaseDocumentDriveServer
|
|
|
403
403
|
undefined,
|
|
404
404
|
undefined,
|
|
405
405
|
undefined,
|
|
406
|
-
drive
|
|
406
|
+
drive,
|
|
407
407
|
);
|
|
408
408
|
|
|
409
409
|
for (const trigger of drive.state.local.triggers) {
|
|
@@ -439,13 +439,13 @@ export class BaseDocumentDriveServer
|
|
|
439
439
|
driveId,
|
|
440
440
|
trigger,
|
|
441
441
|
error.response.status,
|
|
442
|
-
error.message
|
|
442
|
+
error.message,
|
|
443
443
|
);
|
|
444
444
|
}
|
|
445
445
|
},
|
|
446
446
|
(revisions) => {
|
|
447
447
|
const errorRevision = revisions.filter(
|
|
448
|
-
(r) => r.status !== "SUCCESS"
|
|
448
|
+
(r) => r.status !== "SUCCESS",
|
|
449
449
|
);
|
|
450
450
|
|
|
451
451
|
if (errorRevision.length < 1) {
|
|
@@ -462,14 +462,14 @@ export class BaseDocumentDriveServer
|
|
|
462
462
|
.then((revSyncUnits) => {
|
|
463
463
|
for (const syncUnit of revSyncUnits) {
|
|
464
464
|
const fileErrorRevision = errorRevision.find(
|
|
465
|
-
(r) => r.documentId === syncUnit.documentId
|
|
465
|
+
(r) => r.documentId === syncUnit.documentId,
|
|
466
466
|
);
|
|
467
467
|
|
|
468
468
|
if (fileErrorRevision) {
|
|
469
469
|
this.updateSyncUnitStatus(
|
|
470
470
|
syncUnit.syncId,
|
|
471
471
|
{ pull: fileErrorRevision.status },
|
|
472
|
-
fileErrorRevision.error
|
|
472
|
+
fileErrorRevision.error,
|
|
473
473
|
);
|
|
474
474
|
} else {
|
|
475
475
|
this.updateSyncUnitStatus(syncUnit.syncId, {
|
|
@@ -485,7 +485,7 @@ export class BaseDocumentDriveServer
|
|
|
485
485
|
if (firstPull) {
|
|
486
486
|
firstPull = false;
|
|
487
487
|
const pushListener = drive.state.local.listeners.find(
|
|
488
|
-
(listener) => trigger.data.url === listener.callInfo?.data
|
|
488
|
+
(listener) => trigger.data.url === listener.callInfo?.data,
|
|
489
489
|
);
|
|
490
490
|
if (pushListener) {
|
|
491
491
|
this.getSynchronizationUnitsRevision(driveId, syncUnits)
|
|
@@ -496,7 +496,7 @@ export class BaseDocumentDriveServer
|
|
|
496
496
|
pushListener.listenerId,
|
|
497
497
|
driveId,
|
|
498
498
|
revision.syncId,
|
|
499
|
-
revision.revision
|
|
499
|
+
revision.revision,
|
|
500
500
|
)
|
|
501
501
|
.catch(logger.error);
|
|
502
502
|
}
|
|
@@ -504,7 +504,7 @@ export class BaseDocumentDriveServer
|
|
|
504
504
|
.catch(logger.error);
|
|
505
505
|
}
|
|
506
506
|
}
|
|
507
|
-
}
|
|
507
|
+
},
|
|
508
508
|
);
|
|
509
509
|
driveTriggers.set(trigger.id, cancelPullLoop);
|
|
510
510
|
this.triggerMap.set(driveId, driveTriggers);
|
|
@@ -537,7 +537,7 @@ export class BaseDocumentDriveServer
|
|
|
537
537
|
private queueDelegate = {
|
|
538
538
|
checkDocumentExists: (
|
|
539
539
|
driveId: string,
|
|
540
|
-
documentId: string
|
|
540
|
+
documentId: string,
|
|
541
541
|
): Promise<boolean> =>
|
|
542
542
|
this.storage.checkDocumentExists(driveId, documentId),
|
|
543
543
|
processOperationJob: async ({
|
|
@@ -551,7 +551,7 @@ export class BaseDocumentDriveServer
|
|
|
551
551
|
: this.addDriveOperations(
|
|
552
552
|
driveId,
|
|
553
553
|
operations as Operation<DocumentDriveAction | BaseAction>[],
|
|
554
|
-
options
|
|
554
|
+
options,
|
|
555
555
|
);
|
|
556
556
|
},
|
|
557
557
|
processActionJob: async ({
|
|
@@ -565,7 +565,7 @@ export class BaseDocumentDriveServer
|
|
|
565
565
|
: this.addDriveActions(
|
|
566
566
|
driveId,
|
|
567
567
|
actions as Operation<DocumentDriveAction | BaseAction>[],
|
|
568
|
-
options
|
|
568
|
+
options,
|
|
569
569
|
);
|
|
570
570
|
},
|
|
571
571
|
processJob: async (job: Job) => {
|
|
@@ -616,7 +616,7 @@ export class BaseDocumentDriveServer
|
|
|
616
616
|
.triggerUpdate(
|
|
617
617
|
false,
|
|
618
618
|
{ type: "local" },
|
|
619
|
-
this.handleListenerError.bind(this)
|
|
619
|
+
this.handleListenerError.bind(this),
|
|
620
620
|
)
|
|
621
621
|
.catch((error) => {
|
|
622
622
|
logger.error("Non handled error updating listeners", error);
|
|
@@ -644,7 +644,7 @@ export class BaseDocumentDriveServer
|
|
|
644
644
|
scope?: string[],
|
|
645
645
|
branch?: string[],
|
|
646
646
|
documentType?: string[],
|
|
647
|
-
loadedDrive?: DocumentDriveDocument
|
|
647
|
+
loadedDrive?: DocumentDriveDocument,
|
|
648
648
|
) {
|
|
649
649
|
const drive = loadedDrive || (await this.getDrive(driveId));
|
|
650
650
|
|
|
@@ -654,19 +654,19 @@ export class BaseDocumentDriveServer
|
|
|
654
654
|
scope,
|
|
655
655
|
branch,
|
|
656
656
|
documentType,
|
|
657
|
-
drive
|
|
657
|
+
drive,
|
|
658
658
|
);
|
|
659
659
|
return this.getSynchronizationUnitsRevision(
|
|
660
660
|
driveId,
|
|
661
661
|
synchronizationUnitsQuery,
|
|
662
|
-
drive
|
|
662
|
+
drive,
|
|
663
663
|
);
|
|
664
664
|
}
|
|
665
665
|
|
|
666
666
|
public async getSynchronizationUnitsRevision(
|
|
667
667
|
driveId: string,
|
|
668
668
|
syncUnitsQuery: SynchronizationUnitQuery[],
|
|
669
|
-
loadedDrive?: DocumentDriveDocument
|
|
669
|
+
loadedDrive?: DocumentDriveDocument,
|
|
670
670
|
): Promise<SynchronizationUnit[]> {
|
|
671
671
|
const drive = loadedDrive || (await this.getDrive(driveId));
|
|
672
672
|
|
|
@@ -678,7 +678,7 @@ export class BaseDocumentDriveServer
|
|
|
678
678
|
...s,
|
|
679
679
|
lastUpdated: drive.created,
|
|
680
680
|
revision: -1,
|
|
681
|
-
})
|
|
681
|
+
}),
|
|
682
682
|
);
|
|
683
683
|
for (const revision of revisions) {
|
|
684
684
|
const syncUnit = synchronizationUnits.find(
|
|
@@ -686,7 +686,7 @@ export class BaseDocumentDriveServer
|
|
|
686
686
|
revision.driveId === s.driveId &&
|
|
687
687
|
revision.documentId === s.documentId &&
|
|
688
688
|
revision.scope === s.scope &&
|
|
689
|
-
revision.branch === s.branch
|
|
689
|
+
revision.branch === s.branch,
|
|
690
690
|
);
|
|
691
691
|
if (syncUnit) {
|
|
692
692
|
syncUnit.revision = revision.revision;
|
|
@@ -702,7 +702,7 @@ export class BaseDocumentDriveServer
|
|
|
702
702
|
scope?: string[],
|
|
703
703
|
branch?: string[],
|
|
704
704
|
documentType?: string[],
|
|
705
|
-
loadedDrive?: DocumentDriveDocument
|
|
705
|
+
loadedDrive?: DocumentDriveDocument,
|
|
706
706
|
): Promise<SynchronizationUnitQuery[]> {
|
|
707
707
|
const drive = loadedDrive ?? (await this.getDrive(driveId));
|
|
708
708
|
const nodes = drive.state.global.nodes.filter(
|
|
@@ -713,7 +713,7 @@ export class BaseDocumentDriveServer
|
|
|
713
713
|
documentId.includes("*")) &&
|
|
714
714
|
(!documentType?.length ||
|
|
715
715
|
documentType.includes(node.documentType) ||
|
|
716
|
-
documentType.includes("*"))
|
|
716
|
+
documentType.includes("*")),
|
|
717
717
|
) as Pick<FileNode, "id" | "documentType" | "synchronizationUnits">[];
|
|
718
718
|
|
|
719
719
|
// checks if document drive synchronization unit should be added
|
|
@@ -750,7 +750,7 @@ export class BaseDocumentDriveServer
|
|
|
750
750
|
scope.includes("*")) &&
|
|
751
751
|
(!branch?.length ||
|
|
752
752
|
branch.includes(unit.branch) ||
|
|
753
|
-
branch.includes("*"))
|
|
753
|
+
branch.includes("*")),
|
|
754
754
|
)
|
|
755
755
|
: node.synchronizationUnits;
|
|
756
756
|
if (!nodeUnits.length) {
|
|
@@ -764,7 +764,7 @@ export class BaseDocumentDriveServer
|
|
|
764
764
|
documentType: node.documentType,
|
|
765
765
|
scope: n.scope,
|
|
766
766
|
branch: n.branch,
|
|
767
|
-
}))
|
|
767
|
+
})),
|
|
768
768
|
);
|
|
769
769
|
}
|
|
770
770
|
return synchronizationUnitsQuery;
|
|
@@ -773,13 +773,13 @@ export class BaseDocumentDriveServer
|
|
|
773
773
|
public async getSynchronizationUnitIdInfo(
|
|
774
774
|
driveId: string,
|
|
775
775
|
syncId: string,
|
|
776
|
-
loadedDrive?: DocumentDriveDocument
|
|
776
|
+
loadedDrive?: DocumentDriveDocument,
|
|
777
777
|
): Promise<SynchronizationUnitQuery | undefined> {
|
|
778
778
|
const drive = loadedDrive || (await this.getDrive(driveId));
|
|
779
779
|
const node = drive.state.global.nodes.find(
|
|
780
780
|
(node) =>
|
|
781
781
|
isFileNode(node) &&
|
|
782
|
-
node.synchronizationUnits.find((unit) => unit.syncId === syncId)
|
|
782
|
+
node.synchronizationUnits.find((unit) => unit.syncId === syncId),
|
|
783
783
|
);
|
|
784
784
|
|
|
785
785
|
if (!node || !isFileNode(node)) {
|
|
@@ -787,7 +787,7 @@ export class BaseDocumentDriveServer
|
|
|
787
787
|
}
|
|
788
788
|
|
|
789
789
|
const syncUnit = node.synchronizationUnits.find(
|
|
790
|
-
(unit) => unit.syncId === syncId
|
|
790
|
+
(unit) => unit.syncId === syncId,
|
|
791
791
|
);
|
|
792
792
|
if (!syncUnit) {
|
|
793
793
|
return undefined;
|
|
@@ -806,12 +806,12 @@ export class BaseDocumentDriveServer
|
|
|
806
806
|
public async getSynchronizationUnit(
|
|
807
807
|
driveId: string,
|
|
808
808
|
syncId: string,
|
|
809
|
-
loadedDrive?: DocumentDriveDocument
|
|
809
|
+
loadedDrive?: DocumentDriveDocument,
|
|
810
810
|
): Promise<SynchronizationUnit | undefined> {
|
|
811
811
|
const syncUnit = await this.getSynchronizationUnitIdInfo(
|
|
812
812
|
driveId,
|
|
813
813
|
syncId,
|
|
814
|
-
loadedDrive
|
|
814
|
+
loadedDrive,
|
|
815
815
|
);
|
|
816
816
|
|
|
817
817
|
if (!syncUnit) {
|
|
@@ -841,7 +841,7 @@ export class BaseDocumentDriveServer
|
|
|
841
841
|
driveId: string,
|
|
842
842
|
syncId: string,
|
|
843
843
|
filter: GetStrandsOptions,
|
|
844
|
-
loadedDrive?: DocumentDriveDocument
|
|
844
|
+
loadedDrive?: DocumentDriveDocument,
|
|
845
845
|
): Promise<OperationUpdate[]> {
|
|
846
846
|
const syncUnit =
|
|
847
847
|
syncId === "0"
|
|
@@ -866,7 +866,7 @@ export class BaseDocumentDriveServer
|
|
|
866
866
|
((filter.since === undefined ||
|
|
867
867
|
isBefore(filter.since, operation.timestamp)) &&
|
|
868
868
|
(filter.fromRevision === undefined ||
|
|
869
|
-
operation.index > filter.fromRevision))
|
|
869
|
+
operation.index > filter.fromRevision)),
|
|
870
870
|
);
|
|
871
871
|
|
|
872
872
|
const limitedOperations = filter.limit
|
|
@@ -887,7 +887,7 @@ export class BaseDocumentDriveServer
|
|
|
887
887
|
|
|
888
888
|
protected getDocumentModel(documentType: string) {
|
|
889
889
|
const documentModel = this.documentModels.find(
|
|
890
|
-
(model) => model.documentModel.id === documentType
|
|
890
|
+
(model) => model.documentModel.id === documentType,
|
|
891
891
|
);
|
|
892
892
|
if (!documentModel) {
|
|
893
893
|
throw new Error(`Document type ${documentType} not supported`);
|
|
@@ -929,7 +929,7 @@ export class BaseDocumentDriveServer
|
|
|
929
929
|
|
|
930
930
|
async addRemoteDrive(
|
|
931
931
|
url: string,
|
|
932
|
-
options: RemoteDriveOptions
|
|
932
|
+
options: RemoteDriveOptions,
|
|
933
933
|
): Promise<DocumentDriveDocument> {
|
|
934
934
|
const { id, name, slug, icon } =
|
|
935
935
|
options.expectedDriveInfo || (await requestPublicDrive(url));
|
|
@@ -968,13 +968,13 @@ export class BaseDocumentDriveServer
|
|
|
968
968
|
public async registerPullResponderTrigger(
|
|
969
969
|
id: string,
|
|
970
970
|
url: string,
|
|
971
|
-
options: Pick<RemoteDriveOptions, "pullFilter" | "pullInterval"
|
|
971
|
+
options: Pick<RemoteDriveOptions, "pullFilter" | "pullInterval">,
|
|
972
972
|
) {
|
|
973
973
|
const pullTrigger =
|
|
974
974
|
await PullResponderTransmitter.createPullResponderTrigger(
|
|
975
975
|
id,
|
|
976
976
|
url,
|
|
977
|
-
options
|
|
977
|
+
options,
|
|
978
978
|
);
|
|
979
979
|
|
|
980
980
|
return pullTrigger;
|
|
@@ -1106,14 +1106,14 @@ export class BaseDocumentDriveServer
|
|
|
1106
1106
|
await this.storage.addDriveOperations(
|
|
1107
1107
|
driveId,
|
|
1108
1108
|
operations as Operation<DocumentDriveAction>[],
|
|
1109
|
-
document
|
|
1109
|
+
document,
|
|
1110
1110
|
);
|
|
1111
1111
|
} else {
|
|
1112
1112
|
await this.storage.addDocumentOperations(
|
|
1113
1113
|
driveId,
|
|
1114
1114
|
input.id,
|
|
1115
1115
|
operations,
|
|
1116
|
-
document
|
|
1116
|
+
document,
|
|
1117
1117
|
);
|
|
1118
1118
|
}
|
|
1119
1119
|
}
|
|
@@ -1141,7 +1141,7 @@ export class BaseDocumentDriveServer
|
|
|
1141
1141
|
drive: string,
|
|
1142
1142
|
documentId: string | undefined,
|
|
1143
1143
|
documentStorage: DocumentStorage<T>,
|
|
1144
|
-
operations: Operation<A | BaseAction>[]
|
|
1144
|
+
operations: Operation<A | BaseAction>[],
|
|
1145
1145
|
) {
|
|
1146
1146
|
const operationsApplied: Operation<A | BaseAction>[] = [];
|
|
1147
1147
|
const signals: SignalResult[] = [];
|
|
@@ -1149,7 +1149,7 @@ export class BaseDocumentDriveServer
|
|
|
1149
1149
|
const documentStorageWithState = await this._addDocumentResultingStage(
|
|
1150
1150
|
documentStorage,
|
|
1151
1151
|
drive,
|
|
1152
|
-
documentId
|
|
1152
|
+
documentId,
|
|
1153
1153
|
);
|
|
1154
1154
|
|
|
1155
1155
|
let document: T = this._buildDocument(documentStorageWithState);
|
|
@@ -1163,7 +1163,7 @@ export class BaseDocumentDriveServer
|
|
|
1163
1163
|
// TODO two equal operations done by two clients will be considered the same, ie: { type: "INCREMENT" }
|
|
1164
1164
|
const branch = removeExistingOperations(
|
|
1165
1165
|
operationsByScope[scope as OperationScope] || [],
|
|
1166
|
-
storageDocumentOperations
|
|
1166
|
+
storageDocumentOperations,
|
|
1167
1167
|
);
|
|
1168
1168
|
|
|
1169
1169
|
// No operations to apply
|
|
@@ -1181,7 +1181,7 @@ export class BaseDocumentDriveServer
|
|
|
1181
1181
|
: merge(trunk, invertedTrunk, reshuffleByTimestamp);
|
|
1182
1182
|
|
|
1183
1183
|
const newOperations = newHistory.filter(
|
|
1184
|
-
(op) => trunk.length < 1 || precedes(trunk[trunk.length - 1]!, op)
|
|
1184
|
+
(op) => trunk.length < 1 || precedes(trunk[trunk.length - 1]!, op),
|
|
1185
1185
|
);
|
|
1186
1186
|
|
|
1187
1187
|
for (const nextOperation of newOperations) {
|
|
@@ -1191,7 +1191,7 @@ export class BaseDocumentDriveServer
|
|
|
1191
1191
|
// for the operations that were re-indexed (previous hash becomes invalid due the new position in the history)
|
|
1192
1192
|
if (tail.length > 0) {
|
|
1193
1193
|
const sourceOperation = operations.find(
|
|
1194
|
-
(op) => op.hash === nextOperation.hash
|
|
1194
|
+
(op) => op.hash === nextOperation.hash,
|
|
1195
1195
|
);
|
|
1196
1196
|
|
|
1197
1197
|
skipHashValidation =
|
|
@@ -1209,7 +1209,7 @@ export class BaseDocumentDriveServer
|
|
|
1209
1209
|
documentId,
|
|
1210
1210
|
document,
|
|
1211
1211
|
nextOperation,
|
|
1212
|
-
skipHashValidation
|
|
1212
|
+
skipHashValidation,
|
|
1213
1213
|
);
|
|
1214
1214
|
const appliedResult = await (taskQueueMethod
|
|
1215
1215
|
? runAsapAsync(task, taskQueueMethod)
|
|
@@ -1227,7 +1227,7 @@ export class BaseDocumentDriveServer
|
|
|
1227
1227
|
"ERROR",
|
|
1228
1228
|
nextOperation,
|
|
1229
1229
|
(e as Error).message,
|
|
1230
|
-
(e as Error).cause
|
|
1230
|
+
(e as Error).cause,
|
|
1231
1231
|
);
|
|
1232
1232
|
|
|
1233
1233
|
// TODO: don't break on errors...
|
|
@@ -1248,7 +1248,7 @@ export class BaseDocumentDriveServer
|
|
|
1248
1248
|
document: DocumentStorage<T>,
|
|
1249
1249
|
drive: string,
|
|
1250
1250
|
documentId?: string,
|
|
1251
|
-
options?: GetDocumentOptions
|
|
1251
|
+
options?: GetDocumentOptions,
|
|
1252
1252
|
): Promise<DocumentStorage<T>> {
|
|
1253
1253
|
// apply skip header operations to all scopes
|
|
1254
1254
|
const operations =
|
|
@@ -1257,7 +1257,7 @@ export class BaseDocumentDriveServer
|
|
|
1257
1257
|
: document.operations;
|
|
1258
1258
|
const documentOperations =
|
|
1259
1259
|
DocumentUtils.documentHelpers.garbageCollectDocumentOperations(
|
|
1260
|
-
operations
|
|
1260
|
+
operations,
|
|
1261
1261
|
);
|
|
1262
1262
|
|
|
1263
1263
|
for (const scope of Object.keys(documentOperations)) {
|
|
@@ -1272,13 +1272,13 @@ export class BaseDocumentDriveServer
|
|
|
1272
1272
|
documentId,
|
|
1273
1273
|
lastRemainingOperation.index,
|
|
1274
1274
|
lastRemainingOperation.scope,
|
|
1275
|
-
"main"
|
|
1275
|
+
"main",
|
|
1276
1276
|
)
|
|
1277
1277
|
: this.storage.getDriveOperationResultingState?.(
|
|
1278
1278
|
drive,
|
|
1279
1279
|
lastRemainingOperation.index,
|
|
1280
1280
|
lastRemainingOperation.scope,
|
|
1281
|
-
"main"
|
|
1281
|
+
"main",
|
|
1282
1282
|
));
|
|
1283
1283
|
}
|
|
1284
1284
|
}
|
|
@@ -1291,7 +1291,7 @@ export class BaseDocumentDriveServer
|
|
|
1291
1291
|
|
|
1292
1292
|
private _buildDocument<T extends Document>(
|
|
1293
1293
|
documentStorage: DocumentStorage<T>,
|
|
1294
|
-
options?: GetDocumentOptions
|
|
1294
|
+
options?: GetDocumentOptions,
|
|
1295
1295
|
): T {
|
|
1296
1296
|
if (documentStorage.state && (!options || options.checkHashes === false)) {
|
|
1297
1297
|
return documentStorage as T;
|
|
@@ -1303,12 +1303,12 @@ export class BaseDocumentDriveServer
|
|
|
1303
1303
|
options?.revisions !== undefined
|
|
1304
1304
|
? filterOperationsByRevision(
|
|
1305
1305
|
documentStorage.operations,
|
|
1306
|
-
options.revisions
|
|
1306
|
+
options.revisions,
|
|
1307
1307
|
)
|
|
1308
1308
|
: documentStorage.operations;
|
|
1309
1309
|
const operations =
|
|
1310
1310
|
baseUtils.documentHelpers.garbageCollectDocumentOperations(
|
|
1311
|
-
revisionOperations
|
|
1311
|
+
revisionOperations,
|
|
1312
1312
|
);
|
|
1313
1313
|
|
|
1314
1314
|
return baseUtils.replayDocument(
|
|
@@ -1322,7 +1322,7 @@ export class BaseDocumentDriveServer
|
|
|
1322
1322
|
...options,
|
|
1323
1323
|
checkHashes: options?.checkHashes ?? true,
|
|
1324
1324
|
reuseOperationResultingState: options?.checkHashes ?? true,
|
|
1325
|
-
}
|
|
1325
|
+
},
|
|
1326
1326
|
) as T;
|
|
1327
1327
|
}
|
|
1328
1328
|
|
|
@@ -1331,7 +1331,7 @@ export class BaseDocumentDriveServer
|
|
|
1331
1331
|
id: string | undefined,
|
|
1332
1332
|
document: T,
|
|
1333
1333
|
operation: Operation,
|
|
1334
|
-
skipHashValidation = false
|
|
1334
|
+
skipHashValidation = false,
|
|
1335
1335
|
) {
|
|
1336
1336
|
const documentModel = this.getDocumentModel(document.documentType);
|
|
1337
1337
|
|
|
@@ -1344,7 +1344,7 @@ export class BaseDocumentDriveServer
|
|
|
1344
1344
|
...document.operations,
|
|
1345
1345
|
[scope]: DocumentUtils.documentHelpers.skipHeaderOperations(
|
|
1346
1346
|
document.operations[scope],
|
|
1347
|
-
operation
|
|
1347
|
+
operation,
|
|
1348
1348
|
),
|
|
1349
1349
|
});
|
|
1350
1350
|
|
|
@@ -1358,13 +1358,13 @@ export class BaseDocumentDriveServer
|
|
|
1358
1358
|
id,
|
|
1359
1359
|
lastRemainingOperation.index,
|
|
1360
1360
|
lastRemainingOperation.scope,
|
|
1361
|
-
"main"
|
|
1361
|
+
"main",
|
|
1362
1362
|
)
|
|
1363
1363
|
: this.storage.getDriveOperationResultingState?.(
|
|
1364
1364
|
drive,
|
|
1365
1365
|
lastRemainingOperation.index,
|
|
1366
1366
|
lastRemainingOperation.scope,
|
|
1367
|
-
"main"
|
|
1367
|
+
"main",
|
|
1368
1368
|
));
|
|
1369
1369
|
}
|
|
1370
1370
|
|
|
@@ -1389,21 +1389,21 @@ export class BaseDocumentDriveServer
|
|
|
1389
1389
|
documentType: documentToCopy.documentType,
|
|
1390
1390
|
document: documentToCopy,
|
|
1391
1391
|
synchronizationUnits: signal.input.synchronizationUnits,
|
|
1392
|
-
})
|
|
1392
|
+
}),
|
|
1393
1393
|
);
|
|
1394
1394
|
break;
|
|
1395
1395
|
}
|
|
1396
1396
|
if (handler) {
|
|
1397
1397
|
operationSignals.push(() =>
|
|
1398
|
-
handler().then((result) => ({ signal, result }))
|
|
1398
|
+
handler().then((result) => ({ signal, result })),
|
|
1399
1399
|
);
|
|
1400
1400
|
}
|
|
1401
1401
|
},
|
|
1402
|
-
{ skip: operation.skip, reuseOperationResultingState: true }
|
|
1402
|
+
{ skip: operation.skip, reuseOperationResultingState: true },
|
|
1403
1403
|
) as T;
|
|
1404
1404
|
|
|
1405
1405
|
const appliedOperations = newDocument.operations[operation.scope].filter(
|
|
1406
|
-
(op) => op.index == operation.index && op.skip == operation.skip
|
|
1406
|
+
(op) => op.index == operation.index && op.skip == operation.skip,
|
|
1407
1407
|
);
|
|
1408
1408
|
const appliedOperation = appliedOperations.at(0);
|
|
1409
1409
|
|
|
@@ -1411,7 +1411,7 @@ export class BaseDocumentDriveServer
|
|
|
1411
1411
|
throw new OperationError(
|
|
1412
1412
|
"ERROR",
|
|
1413
1413
|
operation,
|
|
1414
|
-
`Operation with index ${operation.index}:${operation.skip} was not applied
|
|
1414
|
+
`Operation with index ${operation.index}:${operation.skip} was not applied.`,
|
|
1415
1415
|
);
|
|
1416
1416
|
}
|
|
1417
1417
|
if (
|
|
@@ -1438,7 +1438,7 @@ export class BaseDocumentDriveServer
|
|
|
1438
1438
|
drive: string,
|
|
1439
1439
|
id: string,
|
|
1440
1440
|
operation: Operation,
|
|
1441
|
-
options?: AddOperationOptions
|
|
1441
|
+
options?: AddOperationOptions,
|
|
1442
1442
|
): Promise<IOperationResult> {
|
|
1443
1443
|
return this.addOperations(drive, id, [operation], options);
|
|
1444
1444
|
}
|
|
@@ -1449,7 +1449,7 @@ export class BaseDocumentDriveServer
|
|
|
1449
1449
|
callback: (document: DocumentStorage) => Promise<{
|
|
1450
1450
|
operations: Operation[];
|
|
1451
1451
|
header: DocumentHeader;
|
|
1452
|
-
}
|
|
1452
|
+
}>,
|
|
1453
1453
|
) {
|
|
1454
1454
|
if (!this.storage.addDocumentOperationsWithTransaction) {
|
|
1455
1455
|
const documentStorage = await this.storage.getDocument(drive, id);
|
|
@@ -1460,14 +1460,14 @@ export class BaseDocumentDriveServer
|
|
|
1460
1460
|
drive,
|
|
1461
1461
|
id,
|
|
1462
1462
|
result.operations,
|
|
1463
|
-
result.header
|
|
1463
|
+
result.header,
|
|
1464
1464
|
);
|
|
1465
1465
|
}
|
|
1466
1466
|
} else {
|
|
1467
1467
|
await this.storage.addDocumentOperationsWithTransaction(
|
|
1468
1468
|
drive,
|
|
1469
1469
|
id,
|
|
1470
|
-
callback
|
|
1470
|
+
callback,
|
|
1471
1471
|
);
|
|
1472
1472
|
}
|
|
1473
1473
|
}
|
|
@@ -1476,7 +1476,7 @@ export class BaseDocumentDriveServer
|
|
|
1476
1476
|
drive: string,
|
|
1477
1477
|
id: string,
|
|
1478
1478
|
operation: Operation,
|
|
1479
|
-
options?: AddOperationOptions
|
|
1479
|
+
options?: AddOperationOptions,
|
|
1480
1480
|
): Promise<IOperationResult> {
|
|
1481
1481
|
return this.queueOperations(drive, id, [operation], options);
|
|
1482
1482
|
}
|
|
@@ -1484,7 +1484,7 @@ export class BaseDocumentDriveServer
|
|
|
1484
1484
|
private async resultIfExistingOperations(
|
|
1485
1485
|
drive: string,
|
|
1486
1486
|
id: string,
|
|
1487
|
-
operations: Operation[]
|
|
1487
|
+
operations: Operation[],
|
|
1488
1488
|
): Promise<IOperationResult | undefined> {
|
|
1489
1489
|
try {
|
|
1490
1490
|
const document = await this.getDocument(drive, id);
|
|
@@ -1496,8 +1496,8 @@ export class BaseDocumentDriveServer
|
|
|
1496
1496
|
existingOp.id === op.id &&
|
|
1497
1497
|
existingOp.index === op.index &&
|
|
1498
1498
|
existingOp.type === op.type &&
|
|
1499
|
-
existingOp.hash === op.hash
|
|
1500
|
-
)
|
|
1499
|
+
existingOp.hash === op.hash,
|
|
1500
|
+
),
|
|
1501
1501
|
);
|
|
1502
1502
|
if (!newOperation) {
|
|
1503
1503
|
return {
|
|
@@ -1523,7 +1523,7 @@ export class BaseDocumentDriveServer
|
|
|
1523
1523
|
drive: string,
|
|
1524
1524
|
id: string,
|
|
1525
1525
|
operations: Operation[],
|
|
1526
|
-
options?: AddOperationOptions
|
|
1526
|
+
options?: AddOperationOptions,
|
|
1527
1527
|
) {
|
|
1528
1528
|
// if operations are already stored then returns cached document
|
|
1529
1529
|
const result = await this.resultIfExistingOperations(drive, id, operations);
|
|
@@ -1547,7 +1547,7 @@ export class BaseDocumentDriveServer
|
|
|
1547
1547
|
unsubscribeError();
|
|
1548
1548
|
resolve(result);
|
|
1549
1549
|
}
|
|
1550
|
-
}
|
|
1550
|
+
},
|
|
1551
1551
|
);
|
|
1552
1552
|
const unsubscribeError = this.queueManager.on(
|
|
1553
1553
|
"jobFailed",
|
|
@@ -1557,7 +1557,7 @@ export class BaseDocumentDriveServer
|
|
|
1557
1557
|
unsubscribeError();
|
|
1558
1558
|
reject(error);
|
|
1559
1559
|
}
|
|
1560
|
-
}
|
|
1560
|
+
},
|
|
1561
1561
|
);
|
|
1562
1562
|
});
|
|
1563
1563
|
} catch (error) {
|
|
@@ -1570,7 +1570,7 @@ export class BaseDocumentDriveServer
|
|
|
1570
1570
|
drive: string,
|
|
1571
1571
|
id: string,
|
|
1572
1572
|
action: Action,
|
|
1573
|
-
options?: AddOperationOptions
|
|
1573
|
+
options?: AddOperationOptions,
|
|
1574
1574
|
): Promise<IOperationResult> {
|
|
1575
1575
|
return this.queueActions(drive, id, [action], options);
|
|
1576
1576
|
}
|
|
@@ -1579,7 +1579,7 @@ export class BaseDocumentDriveServer
|
|
|
1579
1579
|
drive: string,
|
|
1580
1580
|
id: string,
|
|
1581
1581
|
actions: Action[],
|
|
1582
|
-
options?: AddOperationOptions
|
|
1582
|
+
options?: AddOperationOptions,
|
|
1583
1583
|
): Promise<IOperationResult> {
|
|
1584
1584
|
try {
|
|
1585
1585
|
const jobId = await this.queueManager.addJob({
|
|
@@ -1598,7 +1598,7 @@ export class BaseDocumentDriveServer
|
|
|
1598
1598
|
unsubscribeError();
|
|
1599
1599
|
resolve(result);
|
|
1600
1600
|
}
|
|
1601
|
-
}
|
|
1601
|
+
},
|
|
1602
1602
|
);
|
|
1603
1603
|
const unsubscribeError = this.queueManager.on(
|
|
1604
1604
|
"jobFailed",
|
|
@@ -1608,7 +1608,7 @@ export class BaseDocumentDriveServer
|
|
|
1608
1608
|
unsubscribeError();
|
|
1609
1609
|
reject(error);
|
|
1610
1610
|
}
|
|
1611
|
-
}
|
|
1611
|
+
},
|
|
1612
1612
|
);
|
|
1613
1613
|
});
|
|
1614
1614
|
} catch (error) {
|
|
@@ -1620,7 +1620,7 @@ export class BaseDocumentDriveServer
|
|
|
1620
1620
|
async queueDriveAction(
|
|
1621
1621
|
drive: string,
|
|
1622
1622
|
action: DocumentDriveAction | BaseAction,
|
|
1623
|
-
options?: AddOperationOptions
|
|
1623
|
+
options?: AddOperationOptions,
|
|
1624
1624
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1625
1625
|
return this.queueDriveActions(drive, [action], options);
|
|
1626
1626
|
}
|
|
@@ -1628,7 +1628,7 @@ export class BaseDocumentDriveServer
|
|
|
1628
1628
|
async queueDriveActions(
|
|
1629
1629
|
drive: string,
|
|
1630
1630
|
actions: (DocumentDriveAction | BaseAction)[],
|
|
1631
|
-
options?: AddOperationOptions
|
|
1631
|
+
options?: AddOperationOptions,
|
|
1632
1632
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1633
1633
|
try {
|
|
1634
1634
|
const jobId = await this.queueManager.addJob({
|
|
@@ -1646,7 +1646,7 @@ export class BaseDocumentDriveServer
|
|
|
1646
1646
|
unsubscribeError();
|
|
1647
1647
|
resolve(result as IOperationResult<DocumentDriveDocument>);
|
|
1648
1648
|
}
|
|
1649
|
-
}
|
|
1649
|
+
},
|
|
1650
1650
|
);
|
|
1651
1651
|
const unsubscribeError = this.queueManager.on(
|
|
1652
1652
|
"jobFailed",
|
|
@@ -1656,9 +1656,9 @@ export class BaseDocumentDriveServer
|
|
|
1656
1656
|
unsubscribeError();
|
|
1657
1657
|
reject(error);
|
|
1658
1658
|
}
|
|
1659
|
-
}
|
|
1659
|
+
},
|
|
1660
1660
|
);
|
|
1661
|
-
}
|
|
1661
|
+
},
|
|
1662
1662
|
);
|
|
1663
1663
|
} catch (error) {
|
|
1664
1664
|
logger.error("Error adding drive job", error);
|
|
@@ -1670,7 +1670,7 @@ export class BaseDocumentDriveServer
|
|
|
1670
1670
|
drive: string,
|
|
1671
1671
|
id: string,
|
|
1672
1672
|
operations: Operation[],
|
|
1673
|
-
options?: AddOperationOptions
|
|
1673
|
+
options?: AddOperationOptions,
|
|
1674
1674
|
) {
|
|
1675
1675
|
// if operations are already stored then returns the result
|
|
1676
1676
|
const result = await this.resultIfExistingOperations(drive, id, operations);
|
|
@@ -1688,7 +1688,7 @@ export class BaseDocumentDriveServer
|
|
|
1688
1688
|
drive,
|
|
1689
1689
|
id,
|
|
1690
1690
|
documentStorage,
|
|
1691
|
-
operations
|
|
1691
|
+
operations,
|
|
1692
1692
|
);
|
|
1693
1693
|
|
|
1694
1694
|
if (!result.document) {
|
|
@@ -1720,14 +1720,14 @@ export class BaseDocumentDriveServer
|
|
|
1720
1720
|
}
|
|
1721
1721
|
return acc;
|
|
1722
1722
|
},
|
|
1723
|
-
{ scopes: [] as string[], branches: ["main"] }
|
|
1723
|
+
{ scopes: [] as string[], branches: ["main"] },
|
|
1724
1724
|
);
|
|
1725
1725
|
|
|
1726
1726
|
const syncUnits = await this.getSynchronizationUnits(
|
|
1727
1727
|
drive,
|
|
1728
1728
|
[id],
|
|
1729
1729
|
scopes,
|
|
1730
|
-
branches
|
|
1730
|
+
branches,
|
|
1731
1731
|
);
|
|
1732
1732
|
|
|
1733
1733
|
// checks if any of the provided operations where reshufled
|
|
@@ -1738,8 +1738,8 @@ export class BaseDocumentDriveServer
|
|
|
1738
1738
|
o.id === appliedOp.id &&
|
|
1739
1739
|
o.index === appliedOp.index &&
|
|
1740
1740
|
o.skip === appliedOp.skip &&
|
|
1741
|
-
o.hash === appliedOp.hash
|
|
1742
|
-
)
|
|
1741
|
+
o.hash === appliedOp.hash,
|
|
1742
|
+
),
|
|
1743
1743
|
);
|
|
1744
1744
|
|
|
1745
1745
|
// if there are no new operations then reuses the provided source
|
|
@@ -1770,7 +1770,7 @@ export class BaseDocumentDriveServer
|
|
|
1770
1770
|
}
|
|
1771
1771
|
},
|
|
1772
1772
|
this.handleListenerError.bind(this),
|
|
1773
|
-
options?.forceSync ?? source.type === "local"
|
|
1773
|
+
options?.forceSync ?? source.type === "local",
|
|
1774
1774
|
)
|
|
1775
1775
|
.then((updates) => {
|
|
1776
1776
|
if (updates.length) {
|
|
@@ -1792,7 +1792,7 @@ export class BaseDocumentDriveServer
|
|
|
1792
1792
|
{
|
|
1793
1793
|
[operationSource]: "ERROR",
|
|
1794
1794
|
},
|
|
1795
|
-
error as Error
|
|
1795
|
+
error as Error,
|
|
1796
1796
|
);
|
|
1797
1797
|
|
|
1798
1798
|
for (const syncUnit of syncUnits) {
|
|
@@ -1801,7 +1801,7 @@ export class BaseDocumentDriveServer
|
|
|
1801
1801
|
{
|
|
1802
1802
|
[operationSource]: "ERROR",
|
|
1803
1803
|
},
|
|
1804
|
-
error as Error
|
|
1804
|
+
error as Error,
|
|
1805
1805
|
);
|
|
1806
1806
|
}
|
|
1807
1807
|
});
|
|
@@ -1826,7 +1826,7 @@ export class BaseDocumentDriveServer
|
|
|
1826
1826
|
"ERROR",
|
|
1827
1827
|
undefined,
|
|
1828
1828
|
(error as Error).message,
|
|
1829
|
-
(error as Error).cause
|
|
1829
|
+
(error as Error).cause,
|
|
1830
1830
|
);
|
|
1831
1831
|
|
|
1832
1832
|
return {
|
|
@@ -1842,7 +1842,7 @@ export class BaseDocumentDriveServer
|
|
|
1842
1842
|
addDriveOperation(
|
|
1843
1843
|
drive: string,
|
|
1844
1844
|
operation: Operation<DocumentDriveAction | BaseAction>,
|
|
1845
|
-
options?: AddOperationOptions
|
|
1845
|
+
options?: AddOperationOptions,
|
|
1846
1846
|
) {
|
|
1847
1847
|
return this.addDriveOperations(drive, [operation], options);
|
|
1848
1848
|
}
|
|
@@ -1860,7 +1860,7 @@ export class BaseDocumentDriveServer
|
|
|
1860
1860
|
callback: (document: DocumentDriveStorage) => Promise<{
|
|
1861
1861
|
operations: Operation<DocumentDriveAction | BaseAction>[];
|
|
1862
1862
|
header: DocumentHeader;
|
|
1863
|
-
}
|
|
1863
|
+
}>,
|
|
1864
1864
|
) {
|
|
1865
1865
|
if (!this.storage.addDriveOperationsWithTransaction) {
|
|
1866
1866
|
const documentStorage = await this.storage.getDrive(drive);
|
|
@@ -1870,7 +1870,7 @@ export class BaseDocumentDriveServer
|
|
|
1870
1870
|
await this.storage.addDriveOperations(
|
|
1871
1871
|
drive,
|
|
1872
1872
|
result.operations,
|
|
1873
|
-
result.header
|
|
1873
|
+
result.header,
|
|
1874
1874
|
);
|
|
1875
1875
|
}
|
|
1876
1876
|
return result;
|
|
@@ -1882,14 +1882,14 @@ export class BaseDocumentDriveServer
|
|
|
1882
1882
|
queueDriveOperation(
|
|
1883
1883
|
drive: string,
|
|
1884
1884
|
operation: Operation<DocumentDriveAction | BaseAction>,
|
|
1885
|
-
options?: AddOperationOptions
|
|
1885
|
+
options?: AddOperationOptions,
|
|
1886
1886
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1887
1887
|
return this.queueDriveOperations(drive, [operation], options);
|
|
1888
1888
|
}
|
|
1889
1889
|
|
|
1890
1890
|
private async resultIfExistingDriveOperations(
|
|
1891
1891
|
driveId: string,
|
|
1892
|
-
operations: Operation<DocumentDriveAction | BaseAction>[]
|
|
1892
|
+
operations: Operation<DocumentDriveAction | BaseAction>[],
|
|
1893
1893
|
): Promise<IOperationResult<DocumentDriveDocument> | undefined> {
|
|
1894
1894
|
try {
|
|
1895
1895
|
const drive = await this.getDrive(driveId);
|
|
@@ -1901,8 +1901,8 @@ export class BaseDocumentDriveServer
|
|
|
1901
1901
|
existingOp.id === op.id &&
|
|
1902
1902
|
existingOp.index === op.index &&
|
|
1903
1903
|
existingOp.type === op.type &&
|
|
1904
|
-
existingOp.hash === op.hash
|
|
1905
|
-
)
|
|
1904
|
+
existingOp.hash === op.hash,
|
|
1905
|
+
),
|
|
1906
1906
|
);
|
|
1907
1907
|
if (!newOperation) {
|
|
1908
1908
|
return {
|
|
@@ -1923,12 +1923,12 @@ export class BaseDocumentDriveServer
|
|
|
1923
1923
|
async queueDriveOperations(
|
|
1924
1924
|
drive: string,
|
|
1925
1925
|
operations: Operation<DocumentDriveAction | BaseAction>[],
|
|
1926
|
-
options?: AddOperationOptions
|
|
1926
|
+
options?: AddOperationOptions,
|
|
1927
1927
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1928
1928
|
// if operations are already stored then returns cached document
|
|
1929
1929
|
const result = await this.resultIfExistingDriveOperations(
|
|
1930
1930
|
drive,
|
|
1931
|
-
operations
|
|
1931
|
+
operations,
|
|
1932
1932
|
);
|
|
1933
1933
|
if (result) {
|
|
1934
1934
|
return result;
|
|
@@ -1949,7 +1949,7 @@ export class BaseDocumentDriveServer
|
|
|
1949
1949
|
unsubscribeError();
|
|
1950
1950
|
resolve(result as IOperationResult<DocumentDriveDocument>);
|
|
1951
1951
|
}
|
|
1952
|
-
}
|
|
1952
|
+
},
|
|
1953
1953
|
);
|
|
1954
1954
|
const unsubscribeError = this.queueManager.on(
|
|
1955
1955
|
"jobFailed",
|
|
@@ -1959,9 +1959,9 @@ export class BaseDocumentDriveServer
|
|
|
1959
1959
|
unsubscribeError();
|
|
1960
1960
|
reject(error);
|
|
1961
1961
|
}
|
|
1962
|
-
}
|
|
1962
|
+
},
|
|
1963
1963
|
);
|
|
1964
|
-
}
|
|
1964
|
+
},
|
|
1965
1965
|
);
|
|
1966
1966
|
} catch (error) {
|
|
1967
1967
|
logger.error("Error adding drive job", error);
|
|
@@ -1972,7 +1972,7 @@ export class BaseDocumentDriveServer
|
|
|
1972
1972
|
async addDriveOperations(
|
|
1973
1973
|
drive: string,
|
|
1974
1974
|
operations: Operation<DocumentDriveAction | BaseAction>[],
|
|
1975
|
-
options?: AddOperationOptions
|
|
1975
|
+
options?: AddOperationOptions,
|
|
1976
1976
|
) {
|
|
1977
1977
|
let document: DocumentDriveDocument | undefined;
|
|
1978
1978
|
const operationsApplied: Operation<DocumentDriveAction | BaseAction>[] = [];
|
|
@@ -1982,7 +1982,7 @@ export class BaseDocumentDriveServer
|
|
|
1982
1982
|
// if operations are already stored then returns cached drive
|
|
1983
1983
|
const result = await this.resultIfExistingDriveOperations(
|
|
1984
1984
|
drive,
|
|
1985
|
-
operations
|
|
1985
|
+
operations,
|
|
1986
1986
|
);
|
|
1987
1987
|
if (result) {
|
|
1988
1988
|
return result;
|
|
@@ -2039,8 +2039,8 @@ export class BaseDocumentDriveServer
|
|
|
2039
2039
|
o.id === appliedOp.id &&
|
|
2040
2040
|
o.index === appliedOp.index &&
|
|
2041
2041
|
o.skip === appliedOp.skip &&
|
|
2042
|
-
o.hash === appliedOp.hash
|
|
2043
|
-
)
|
|
2042
|
+
o.hash === appliedOp.hash,
|
|
2043
|
+
),
|
|
2044
2044
|
);
|
|
2045
2045
|
|
|
2046
2046
|
// if there are no new operations then reuses the provided source
|
|
@@ -2074,7 +2074,7 @@ export class BaseDocumentDriveServer
|
|
|
2074
2074
|
});
|
|
2075
2075
|
},
|
|
2076
2076
|
this.handleListenerError.bind(this),
|
|
2077
|
-
options?.forceSync ?? source.type === "local"
|
|
2077
|
+
options?.forceSync ?? source.type === "local",
|
|
2078
2078
|
)
|
|
2079
2079
|
.then((updates) => {
|
|
2080
2080
|
if (updates.length) {
|
|
@@ -2088,7 +2088,7 @@ export class BaseDocumentDriveServer
|
|
|
2088
2088
|
this.updateSyncUnitStatus(
|
|
2089
2089
|
drive,
|
|
2090
2090
|
{ [operationSource]: "ERROR" },
|
|
2091
|
-
error as Error
|
|
2091
|
+
error as Error,
|
|
2092
2092
|
);
|
|
2093
2093
|
});
|
|
2094
2094
|
}
|
|
@@ -2119,7 +2119,7 @@ export class BaseDocumentDriveServer
|
|
|
2119
2119
|
"ERROR",
|
|
2120
2120
|
undefined,
|
|
2121
2121
|
(error as Error).message,
|
|
2122
|
-
(error as Error).cause
|
|
2122
|
+
(error as Error).cause,
|
|
2123
2123
|
);
|
|
2124
2124
|
|
|
2125
2125
|
return {
|
|
@@ -2134,7 +2134,7 @@ export class BaseDocumentDriveServer
|
|
|
2134
2134
|
|
|
2135
2135
|
private _buildOperations<T extends Action>(
|
|
2136
2136
|
document: Document,
|
|
2137
|
-
actions: (T | BaseAction)[]
|
|
2137
|
+
actions: (T | BaseAction)[],
|
|
2138
2138
|
): Operation<T | BaseAction>[] {
|
|
2139
2139
|
const operations: Operation<T | BaseAction>[] = [];
|
|
2140
2140
|
const { reducer } = this.getDocumentModel(document.documentType);
|
|
@@ -2153,7 +2153,7 @@ export class BaseDocumentDriveServer
|
|
|
2153
2153
|
drive: string,
|
|
2154
2154
|
id: string,
|
|
2155
2155
|
action: Action,
|
|
2156
|
-
options?: AddOperationOptions
|
|
2156
|
+
options?: AddOperationOptions,
|
|
2157
2157
|
): Promise<IOperationResult> {
|
|
2158
2158
|
return this.addActions(drive, id, [action], options);
|
|
2159
2159
|
}
|
|
@@ -2162,7 +2162,7 @@ export class BaseDocumentDriveServer
|
|
|
2162
2162
|
drive: string,
|
|
2163
2163
|
id: string,
|
|
2164
2164
|
actions: Action[],
|
|
2165
|
-
options?: AddOperationOptions
|
|
2165
|
+
options?: AddOperationOptions,
|
|
2166
2166
|
): Promise<IOperationResult> {
|
|
2167
2167
|
const document = await this.getDocument(drive, id);
|
|
2168
2168
|
const operations = this._buildOperations(document, actions);
|
|
@@ -2172,7 +2172,7 @@ export class BaseDocumentDriveServer
|
|
|
2172
2172
|
async addDriveAction(
|
|
2173
2173
|
drive: string,
|
|
2174
2174
|
action: DocumentDriveAction | BaseAction,
|
|
2175
|
-
options?: AddOperationOptions
|
|
2175
|
+
options?: AddOperationOptions,
|
|
2176
2176
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
2177
2177
|
return this.addDriveActions(drive, [action], options);
|
|
2178
2178
|
}
|
|
@@ -2180,7 +2180,7 @@ export class BaseDocumentDriveServer
|
|
|
2180
2180
|
async addDriveActions(
|
|
2181
2181
|
drive: string,
|
|
2182
2182
|
actions: (DocumentDriveAction | BaseAction)[],
|
|
2183
|
-
options?: AddOperationOptions
|
|
2183
|
+
options?: AddOperationOptions,
|
|
2184
2184
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
2185
2185
|
const document = await this.getDrive(drive);
|
|
2186
2186
|
const operations = this._buildOperations(document, actions);
|
|
@@ -2196,7 +2196,7 @@ export class BaseDocumentDriveServer
|
|
|
2196
2196
|
label: string;
|
|
2197
2197
|
block: boolean;
|
|
2198
2198
|
filter: ListenerFilter;
|
|
2199
|
-
}
|
|
2199
|
+
},
|
|
2200
2200
|
) {
|
|
2201
2201
|
const listener: AddListenerInput["listener"] = {
|
|
2202
2202
|
callInfo: {
|
|
@@ -2230,26 +2230,26 @@ export class BaseDocumentDriveServer
|
|
|
2230
2230
|
for (const listener of listeners) {
|
|
2231
2231
|
await this.addDriveAction(
|
|
2232
2232
|
driveId,
|
|
2233
|
-
actions.removeListener({ listenerId: listener.listenerId })
|
|
2233
|
+
actions.removeListener({ listenerId: listener.listenerId }),
|
|
2234
2234
|
);
|
|
2235
2235
|
}
|
|
2236
2236
|
|
|
2237
2237
|
for (const trigger of triggers) {
|
|
2238
2238
|
await this.addDriveAction(
|
|
2239
2239
|
driveId,
|
|
2240
|
-
actions.removeTrigger({ triggerId: trigger.id })
|
|
2240
|
+
actions.removeTrigger({ triggerId: trigger.id }),
|
|
2241
2241
|
);
|
|
2242
2242
|
}
|
|
2243
2243
|
|
|
2244
2244
|
await this.addDriveAction(
|
|
2245
2245
|
driveId,
|
|
2246
|
-
actions.setSharingType({ type: "LOCAL" })
|
|
2246
|
+
actions.setSharingType({ type: "LOCAL" }),
|
|
2247
2247
|
);
|
|
2248
2248
|
}
|
|
2249
2249
|
|
|
2250
2250
|
private async addListener(
|
|
2251
2251
|
driveId: string,
|
|
2252
|
-
operation: Operation<Action<"ADD_LISTENER", AddListenerInput
|
|
2252
|
+
operation: Operation<Action<"ADD_LISTENER", AddListenerInput>>,
|
|
2253
2253
|
) {
|
|
2254
2254
|
const { listener } = operation.input;
|
|
2255
2255
|
await this.listenerStateManager.addListener({
|
|
@@ -2273,7 +2273,7 @@ export class BaseDocumentDriveServer
|
|
|
2273
2273
|
|
|
2274
2274
|
private async removeListener(
|
|
2275
2275
|
driveId: string,
|
|
2276
|
-
operation: Operation<Action<"REMOVE_LISTENER", RemoveListenerInput
|
|
2276
|
+
operation: Operation<Action<"REMOVE_LISTENER", RemoveListenerInput>>,
|
|
2277
2277
|
) {
|
|
2278
2278
|
const { listenerId } = operation.input;
|
|
2279
2279
|
await this.listenerStateManager.removeListener(driveId, listenerId);
|
|
@@ -2281,26 +2281,26 @@ export class BaseDocumentDriveServer
|
|
|
2281
2281
|
|
|
2282
2282
|
getTransmitter(
|
|
2283
2283
|
driveId: string,
|
|
2284
|
-
listenerId: string
|
|
2284
|
+
listenerId: string,
|
|
2285
2285
|
): Promise<ITransmitter | undefined> {
|
|
2286
2286
|
return this.listenerStateManager.getTransmitter(driveId, listenerId);
|
|
2287
2287
|
}
|
|
2288
2288
|
|
|
2289
2289
|
getListener(
|
|
2290
2290
|
driveId: string,
|
|
2291
|
-
listenerId: string
|
|
2291
|
+
listenerId: string,
|
|
2292
2292
|
): Promise<ListenerState | undefined> {
|
|
2293
2293
|
return this.listenerStateManager.getListener(driveId, listenerId);
|
|
2294
2294
|
}
|
|
2295
2295
|
|
|
2296
2296
|
getSyncStatus(
|
|
2297
|
-
syncUnitId: string
|
|
2297
|
+
syncUnitId: string,
|
|
2298
2298
|
): SyncStatus | SynchronizationUnitNotFoundError {
|
|
2299
2299
|
const status = this.syncStatus.get(syncUnitId);
|
|
2300
2300
|
if (!status) {
|
|
2301
2301
|
return new SynchronizationUnitNotFoundError(
|
|
2302
2302
|
`Sync status not found for syncUnitId: ${syncUnitId}`,
|
|
2303
|
-
syncUnitId
|
|
2303
|
+
syncUnitId,
|
|
2304
2304
|
);
|
|
2305
2305
|
}
|
|
2306
2306
|
return this.getCombinedSyncUnitStatus(status);
|
|
@@ -27,6 +27,10 @@ export type InternalTransmitterUpdate<
|
|
|
27
27
|
state: T["state"][S];
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
+
export interface IInternalTransmitter extends ITransmitter {
|
|
31
|
+
setReceiver(receiver: IReceiver): void;
|
|
32
|
+
}
|
|
33
|
+
|
|
30
34
|
export class InternalTransmitter implements ITransmitter {
|
|
31
35
|
private drive: IBaseDocumentDriveServer;
|
|
32
36
|
private listener: Listener;
|
package/src/server/types.ts
CHANGED
|
@@ -22,6 +22,10 @@ import type {
|
|
|
22
22
|
} from "document-model/document";
|
|
23
23
|
import { Unsubscribe } from "nanoevents";
|
|
24
24
|
import { BaseDocumentDriveServer } from ".";
|
|
25
|
+
import {
|
|
26
|
+
IReceiver as IInternalListener,
|
|
27
|
+
IInternalTransmitter,
|
|
28
|
+
} from "./listener/transmitter/internal";
|
|
25
29
|
import { IReadModeDriveServer } from "../read-mode/types";
|
|
26
30
|
import { RunAsap } from "../utils";
|
|
27
31
|
import { IDefaultDrivesManager } from "../utils/default-drives-manager";
|
|
@@ -443,6 +447,17 @@ export abstract class AbstractDocumentDriveServer {
|
|
|
443
447
|
syncUnitId: string,
|
|
444
448
|
): SyncStatus | SynchronizationUnitNotFoundError;
|
|
445
449
|
|
|
450
|
+
abstract addInternalListener(
|
|
451
|
+
driveId: string,
|
|
452
|
+
receiver: IInternalListener,
|
|
453
|
+
options: {
|
|
454
|
+
listenerId: string;
|
|
455
|
+
label: string;
|
|
456
|
+
block: boolean;
|
|
457
|
+
filter: ListenerFilter;
|
|
458
|
+
},
|
|
459
|
+
): Promise<IInternalTransmitter>;
|
|
460
|
+
|
|
446
461
|
/** Synchronization methods */
|
|
447
462
|
abstract getSynchronizationUnits(
|
|
448
463
|
driveId: string,
|
|
@@ -486,12 +501,10 @@ export abstract class AbstractDocumentDriveServer {
|
|
|
486
501
|
|
|
487
502
|
/** Event methods **/
|
|
488
503
|
protected abstract emit<K extends keyof DriveEvents>(
|
|
489
|
-
this: this,
|
|
490
504
|
event: K,
|
|
491
505
|
...args: Parameters<DriveEvents[K]>
|
|
492
506
|
): void;
|
|
493
507
|
abstract on<K extends keyof DriveEvents>(
|
|
494
|
-
this: this,
|
|
495
508
|
event: K,
|
|
496
509
|
cb: DriveEvents[K],
|
|
497
510
|
): Unsubscribe;
|
|
@@ -518,10 +531,13 @@ export const DefaultListenerManagerOptions = {
|
|
|
518
531
|
sequentialUpdates: true,
|
|
519
532
|
};
|
|
520
533
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
534
|
+
type PublicKeys<T> = {
|
|
535
|
+
[K in keyof T]: T extends { [P in K]: T[K] } ? K : never;
|
|
536
|
+
}[keyof T];
|
|
537
|
+
|
|
538
|
+
type PublicPart<T> = Pick<T, PublicKeys<T>>;
|
|
539
|
+
|
|
540
|
+
export type IBaseDocumentDriveServer = PublicPart<AbstractDocumentDriveServer>;
|
|
525
541
|
|
|
526
542
|
export type IDocumentDriveServer = IBaseDocumentDriveServer &
|
|
527
543
|
IDefaultDrivesManager &
|