document-drive 1.1.1 → 1.2.1
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 +2 -2
- package/src/server/index.ts +146 -141
- package/src/server/types.ts +3 -0
- package/src/storage/drizzle/queries.ts +51 -0
- package/src/storage/drizzle.ts +627 -0
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`);
|
|
@@ -895,6 +895,10 @@ export class BaseDocumentDriveServer
|
|
|
895
895
|
return documentModel;
|
|
896
896
|
}
|
|
897
897
|
|
|
898
|
+
getDocumentModels() {
|
|
899
|
+
return [...this.documentModels];
|
|
900
|
+
}
|
|
901
|
+
|
|
898
902
|
async addDrive(drive: DriveInput): Promise<DocumentDriveDocument> {
|
|
899
903
|
const id = drive.global.id || generateUUID();
|
|
900
904
|
if (!id) {
|
|
@@ -918,12 +922,14 @@ export class BaseDocumentDriveServer
|
|
|
918
922
|
|
|
919
923
|
await this._initializeDrive(id);
|
|
920
924
|
|
|
925
|
+
this.emit("driveAdded", document);
|
|
926
|
+
|
|
921
927
|
return document;
|
|
922
928
|
}
|
|
923
929
|
|
|
924
930
|
async addRemoteDrive(
|
|
925
931
|
url: string,
|
|
926
|
-
options: RemoteDriveOptions
|
|
932
|
+
options: RemoteDriveOptions
|
|
927
933
|
): Promise<DocumentDriveDocument> {
|
|
928
934
|
const { id, name, slug, icon } =
|
|
929
935
|
options.expectedDriveInfo || (await requestPublicDrive(url));
|
|
@@ -962,13 +968,13 @@ export class BaseDocumentDriveServer
|
|
|
962
968
|
public async registerPullResponderTrigger(
|
|
963
969
|
id: string,
|
|
964
970
|
url: string,
|
|
965
|
-
options: Pick<RemoteDriveOptions, "pullFilter" | "pullInterval"
|
|
971
|
+
options: Pick<RemoteDriveOptions, "pullFilter" | "pullInterval">
|
|
966
972
|
) {
|
|
967
973
|
const pullTrigger =
|
|
968
974
|
await PullResponderTransmitter.createPullResponderTrigger(
|
|
969
975
|
id,
|
|
970
976
|
url,
|
|
971
|
-
options
|
|
977
|
+
options
|
|
972
978
|
);
|
|
973
979
|
|
|
974
980
|
return pullTrigger;
|
|
@@ -1100,14 +1106,14 @@ export class BaseDocumentDriveServer
|
|
|
1100
1106
|
await this.storage.addDriveOperations(
|
|
1101
1107
|
driveId,
|
|
1102
1108
|
operations as Operation<DocumentDriveAction>[],
|
|
1103
|
-
document
|
|
1109
|
+
document
|
|
1104
1110
|
);
|
|
1105
1111
|
} else {
|
|
1106
1112
|
await this.storage.addDocumentOperations(
|
|
1107
1113
|
driveId,
|
|
1108
1114
|
input.id,
|
|
1109
1115
|
operations,
|
|
1110
|
-
document
|
|
1116
|
+
document
|
|
1111
1117
|
);
|
|
1112
1118
|
}
|
|
1113
1119
|
}
|
|
@@ -1135,7 +1141,7 @@ export class BaseDocumentDriveServer
|
|
|
1135
1141
|
drive: string,
|
|
1136
1142
|
documentId: string | undefined,
|
|
1137
1143
|
documentStorage: DocumentStorage<T>,
|
|
1138
|
-
operations: Operation<A | BaseAction>[]
|
|
1144
|
+
operations: Operation<A | BaseAction>[]
|
|
1139
1145
|
) {
|
|
1140
1146
|
const operationsApplied: Operation<A | BaseAction>[] = [];
|
|
1141
1147
|
const signals: SignalResult[] = [];
|
|
@@ -1143,7 +1149,7 @@ export class BaseDocumentDriveServer
|
|
|
1143
1149
|
const documentStorageWithState = await this._addDocumentResultingStage(
|
|
1144
1150
|
documentStorage,
|
|
1145
1151
|
drive,
|
|
1146
|
-
documentId
|
|
1152
|
+
documentId
|
|
1147
1153
|
);
|
|
1148
1154
|
|
|
1149
1155
|
let document: T = this._buildDocument(documentStorageWithState);
|
|
@@ -1157,7 +1163,7 @@ export class BaseDocumentDriveServer
|
|
|
1157
1163
|
// TODO two equal operations done by two clients will be considered the same, ie: { type: "INCREMENT" }
|
|
1158
1164
|
const branch = removeExistingOperations(
|
|
1159
1165
|
operationsByScope[scope as OperationScope] || [],
|
|
1160
|
-
storageDocumentOperations
|
|
1166
|
+
storageDocumentOperations
|
|
1161
1167
|
);
|
|
1162
1168
|
|
|
1163
1169
|
// No operations to apply
|
|
@@ -1175,7 +1181,7 @@ export class BaseDocumentDriveServer
|
|
|
1175
1181
|
: merge(trunk, invertedTrunk, reshuffleByTimestamp);
|
|
1176
1182
|
|
|
1177
1183
|
const newOperations = newHistory.filter(
|
|
1178
|
-
(op) => trunk.length < 1 || precedes(trunk[trunk.length - 1]!, op)
|
|
1184
|
+
(op) => trunk.length < 1 || precedes(trunk[trunk.length - 1]!, op)
|
|
1179
1185
|
);
|
|
1180
1186
|
|
|
1181
1187
|
for (const nextOperation of newOperations) {
|
|
@@ -1185,7 +1191,7 @@ export class BaseDocumentDriveServer
|
|
|
1185
1191
|
// for the operations that were re-indexed (previous hash becomes invalid due the new position in the history)
|
|
1186
1192
|
if (tail.length > 0) {
|
|
1187
1193
|
const sourceOperation = operations.find(
|
|
1188
|
-
(op) => op.hash === nextOperation.hash
|
|
1194
|
+
(op) => op.hash === nextOperation.hash
|
|
1189
1195
|
);
|
|
1190
1196
|
|
|
1191
1197
|
skipHashValidation =
|
|
@@ -1203,7 +1209,7 @@ export class BaseDocumentDriveServer
|
|
|
1203
1209
|
documentId,
|
|
1204
1210
|
document,
|
|
1205
1211
|
nextOperation,
|
|
1206
|
-
skipHashValidation
|
|
1212
|
+
skipHashValidation
|
|
1207
1213
|
);
|
|
1208
1214
|
const appliedResult = await (taskQueueMethod
|
|
1209
1215
|
? runAsapAsync(task, taskQueueMethod)
|
|
@@ -1221,7 +1227,7 @@ export class BaseDocumentDriveServer
|
|
|
1221
1227
|
"ERROR",
|
|
1222
1228
|
nextOperation,
|
|
1223
1229
|
(e as Error).message,
|
|
1224
|
-
(e as Error).cause
|
|
1230
|
+
(e as Error).cause
|
|
1225
1231
|
);
|
|
1226
1232
|
|
|
1227
1233
|
// TODO: don't break on errors...
|
|
@@ -1242,7 +1248,7 @@ export class BaseDocumentDriveServer
|
|
|
1242
1248
|
document: DocumentStorage<T>,
|
|
1243
1249
|
drive: string,
|
|
1244
1250
|
documentId?: string,
|
|
1245
|
-
options?: GetDocumentOptions
|
|
1251
|
+
options?: GetDocumentOptions
|
|
1246
1252
|
): Promise<DocumentStorage<T>> {
|
|
1247
1253
|
// apply skip header operations to all scopes
|
|
1248
1254
|
const operations =
|
|
@@ -1251,7 +1257,7 @@ export class BaseDocumentDriveServer
|
|
|
1251
1257
|
: document.operations;
|
|
1252
1258
|
const documentOperations =
|
|
1253
1259
|
DocumentUtils.documentHelpers.garbageCollectDocumentOperations(
|
|
1254
|
-
operations
|
|
1260
|
+
operations
|
|
1255
1261
|
);
|
|
1256
1262
|
|
|
1257
1263
|
for (const scope of Object.keys(documentOperations)) {
|
|
@@ -1266,13 +1272,13 @@ export class BaseDocumentDriveServer
|
|
|
1266
1272
|
documentId,
|
|
1267
1273
|
lastRemainingOperation.index,
|
|
1268
1274
|
lastRemainingOperation.scope,
|
|
1269
|
-
"main"
|
|
1275
|
+
"main"
|
|
1270
1276
|
)
|
|
1271
1277
|
: this.storage.getDriveOperationResultingState?.(
|
|
1272
1278
|
drive,
|
|
1273
1279
|
lastRemainingOperation.index,
|
|
1274
1280
|
lastRemainingOperation.scope,
|
|
1275
|
-
"main"
|
|
1281
|
+
"main"
|
|
1276
1282
|
));
|
|
1277
1283
|
}
|
|
1278
1284
|
}
|
|
@@ -1285,7 +1291,7 @@ export class BaseDocumentDriveServer
|
|
|
1285
1291
|
|
|
1286
1292
|
private _buildDocument<T extends Document>(
|
|
1287
1293
|
documentStorage: DocumentStorage<T>,
|
|
1288
|
-
options?: GetDocumentOptions
|
|
1294
|
+
options?: GetDocumentOptions
|
|
1289
1295
|
): T {
|
|
1290
1296
|
if (documentStorage.state && (!options || options.checkHashes === false)) {
|
|
1291
1297
|
return documentStorage as T;
|
|
@@ -1297,12 +1303,12 @@ export class BaseDocumentDriveServer
|
|
|
1297
1303
|
options?.revisions !== undefined
|
|
1298
1304
|
? filterOperationsByRevision(
|
|
1299
1305
|
documentStorage.operations,
|
|
1300
|
-
options.revisions
|
|
1306
|
+
options.revisions
|
|
1301
1307
|
)
|
|
1302
1308
|
: documentStorage.operations;
|
|
1303
1309
|
const operations =
|
|
1304
1310
|
baseUtils.documentHelpers.garbageCollectDocumentOperations(
|
|
1305
|
-
revisionOperations
|
|
1311
|
+
revisionOperations
|
|
1306
1312
|
);
|
|
1307
1313
|
|
|
1308
1314
|
return baseUtils.replayDocument(
|
|
@@ -1316,7 +1322,7 @@ export class BaseDocumentDriveServer
|
|
|
1316
1322
|
...options,
|
|
1317
1323
|
checkHashes: options?.checkHashes ?? true,
|
|
1318
1324
|
reuseOperationResultingState: options?.checkHashes ?? true,
|
|
1319
|
-
}
|
|
1325
|
+
}
|
|
1320
1326
|
) as T;
|
|
1321
1327
|
}
|
|
1322
1328
|
|
|
@@ -1325,7 +1331,7 @@ export class BaseDocumentDriveServer
|
|
|
1325
1331
|
id: string | undefined,
|
|
1326
1332
|
document: T,
|
|
1327
1333
|
operation: Operation,
|
|
1328
|
-
skipHashValidation = false
|
|
1334
|
+
skipHashValidation = false
|
|
1329
1335
|
) {
|
|
1330
1336
|
const documentModel = this.getDocumentModel(document.documentType);
|
|
1331
1337
|
|
|
@@ -1338,7 +1344,7 @@ export class BaseDocumentDriveServer
|
|
|
1338
1344
|
...document.operations,
|
|
1339
1345
|
[scope]: DocumentUtils.documentHelpers.skipHeaderOperations(
|
|
1340
1346
|
document.operations[scope],
|
|
1341
|
-
operation
|
|
1347
|
+
operation
|
|
1342
1348
|
),
|
|
1343
1349
|
});
|
|
1344
1350
|
|
|
@@ -1352,13 +1358,13 @@ export class BaseDocumentDriveServer
|
|
|
1352
1358
|
id,
|
|
1353
1359
|
lastRemainingOperation.index,
|
|
1354
1360
|
lastRemainingOperation.scope,
|
|
1355
|
-
"main"
|
|
1361
|
+
"main"
|
|
1356
1362
|
)
|
|
1357
1363
|
: this.storage.getDriveOperationResultingState?.(
|
|
1358
1364
|
drive,
|
|
1359
1365
|
lastRemainingOperation.index,
|
|
1360
1366
|
lastRemainingOperation.scope,
|
|
1361
|
-
"main"
|
|
1367
|
+
"main"
|
|
1362
1368
|
));
|
|
1363
1369
|
}
|
|
1364
1370
|
|
|
@@ -1383,21 +1389,21 @@ export class BaseDocumentDriveServer
|
|
|
1383
1389
|
documentType: documentToCopy.documentType,
|
|
1384
1390
|
document: documentToCopy,
|
|
1385
1391
|
synchronizationUnits: signal.input.synchronizationUnits,
|
|
1386
|
-
})
|
|
1392
|
+
})
|
|
1387
1393
|
);
|
|
1388
1394
|
break;
|
|
1389
1395
|
}
|
|
1390
1396
|
if (handler) {
|
|
1391
1397
|
operationSignals.push(() =>
|
|
1392
|
-
handler().then((result) => ({ signal, result }))
|
|
1398
|
+
handler().then((result) => ({ signal, result }))
|
|
1393
1399
|
);
|
|
1394
1400
|
}
|
|
1395
1401
|
},
|
|
1396
|
-
{ skip: operation.skip, reuseOperationResultingState: true }
|
|
1402
|
+
{ skip: operation.skip, reuseOperationResultingState: true }
|
|
1397
1403
|
) as T;
|
|
1398
1404
|
|
|
1399
1405
|
const appliedOperations = newDocument.operations[operation.scope].filter(
|
|
1400
|
-
(op) => op.index == operation.index && op.skip == operation.skip
|
|
1406
|
+
(op) => op.index == operation.index && op.skip == operation.skip
|
|
1401
1407
|
);
|
|
1402
1408
|
const appliedOperation = appliedOperations.at(0);
|
|
1403
1409
|
|
|
@@ -1405,7 +1411,7 @@ export class BaseDocumentDriveServer
|
|
|
1405
1411
|
throw new OperationError(
|
|
1406
1412
|
"ERROR",
|
|
1407
1413
|
operation,
|
|
1408
|
-
`Operation with index ${operation.index}:${operation.skip} was not applied
|
|
1414
|
+
`Operation with index ${operation.index}:${operation.skip} was not applied.`
|
|
1409
1415
|
);
|
|
1410
1416
|
}
|
|
1411
1417
|
if (
|
|
@@ -1432,7 +1438,7 @@ export class BaseDocumentDriveServer
|
|
|
1432
1438
|
drive: string,
|
|
1433
1439
|
id: string,
|
|
1434
1440
|
operation: Operation,
|
|
1435
|
-
options?: AddOperationOptions
|
|
1441
|
+
options?: AddOperationOptions
|
|
1436
1442
|
): Promise<IOperationResult> {
|
|
1437
1443
|
return this.addOperations(drive, id, [operation], options);
|
|
1438
1444
|
}
|
|
@@ -1443,7 +1449,7 @@ export class BaseDocumentDriveServer
|
|
|
1443
1449
|
callback: (document: DocumentStorage) => Promise<{
|
|
1444
1450
|
operations: Operation[];
|
|
1445
1451
|
header: DocumentHeader;
|
|
1446
|
-
}
|
|
1452
|
+
}>
|
|
1447
1453
|
) {
|
|
1448
1454
|
if (!this.storage.addDocumentOperationsWithTransaction) {
|
|
1449
1455
|
const documentStorage = await this.storage.getDocument(drive, id);
|
|
@@ -1454,14 +1460,14 @@ export class BaseDocumentDriveServer
|
|
|
1454
1460
|
drive,
|
|
1455
1461
|
id,
|
|
1456
1462
|
result.operations,
|
|
1457
|
-
result.header
|
|
1463
|
+
result.header
|
|
1458
1464
|
);
|
|
1459
1465
|
}
|
|
1460
1466
|
} else {
|
|
1461
1467
|
await this.storage.addDocumentOperationsWithTransaction(
|
|
1462
1468
|
drive,
|
|
1463
1469
|
id,
|
|
1464
|
-
callback
|
|
1470
|
+
callback
|
|
1465
1471
|
);
|
|
1466
1472
|
}
|
|
1467
1473
|
}
|
|
@@ -1470,7 +1476,7 @@ export class BaseDocumentDriveServer
|
|
|
1470
1476
|
drive: string,
|
|
1471
1477
|
id: string,
|
|
1472
1478
|
operation: Operation,
|
|
1473
|
-
options?: AddOperationOptions
|
|
1479
|
+
options?: AddOperationOptions
|
|
1474
1480
|
): Promise<IOperationResult> {
|
|
1475
1481
|
return this.queueOperations(drive, id, [operation], options);
|
|
1476
1482
|
}
|
|
@@ -1478,7 +1484,7 @@ export class BaseDocumentDriveServer
|
|
|
1478
1484
|
private async resultIfExistingOperations(
|
|
1479
1485
|
drive: string,
|
|
1480
1486
|
id: string,
|
|
1481
|
-
operations: Operation[]
|
|
1487
|
+
operations: Operation[]
|
|
1482
1488
|
): Promise<IOperationResult | undefined> {
|
|
1483
1489
|
try {
|
|
1484
1490
|
const document = await this.getDocument(drive, id);
|
|
@@ -1490,8 +1496,8 @@ export class BaseDocumentDriveServer
|
|
|
1490
1496
|
existingOp.id === op.id &&
|
|
1491
1497
|
existingOp.index === op.index &&
|
|
1492
1498
|
existingOp.type === op.type &&
|
|
1493
|
-
existingOp.hash === op.hash
|
|
1494
|
-
)
|
|
1499
|
+
existingOp.hash === op.hash
|
|
1500
|
+
)
|
|
1495
1501
|
);
|
|
1496
1502
|
if (!newOperation) {
|
|
1497
1503
|
return {
|
|
@@ -1517,7 +1523,7 @@ export class BaseDocumentDriveServer
|
|
|
1517
1523
|
drive: string,
|
|
1518
1524
|
id: string,
|
|
1519
1525
|
operations: Operation[],
|
|
1520
|
-
options?: AddOperationOptions
|
|
1526
|
+
options?: AddOperationOptions
|
|
1521
1527
|
) {
|
|
1522
1528
|
// if operations are already stored then returns cached document
|
|
1523
1529
|
const result = await this.resultIfExistingOperations(drive, id, operations);
|
|
@@ -1541,7 +1547,7 @@ export class BaseDocumentDriveServer
|
|
|
1541
1547
|
unsubscribeError();
|
|
1542
1548
|
resolve(result);
|
|
1543
1549
|
}
|
|
1544
|
-
}
|
|
1550
|
+
}
|
|
1545
1551
|
);
|
|
1546
1552
|
const unsubscribeError = this.queueManager.on(
|
|
1547
1553
|
"jobFailed",
|
|
@@ -1551,7 +1557,7 @@ export class BaseDocumentDriveServer
|
|
|
1551
1557
|
unsubscribeError();
|
|
1552
1558
|
reject(error);
|
|
1553
1559
|
}
|
|
1554
|
-
}
|
|
1560
|
+
}
|
|
1555
1561
|
);
|
|
1556
1562
|
});
|
|
1557
1563
|
} catch (error) {
|
|
@@ -1564,7 +1570,7 @@ export class BaseDocumentDriveServer
|
|
|
1564
1570
|
drive: string,
|
|
1565
1571
|
id: string,
|
|
1566
1572
|
action: Action,
|
|
1567
|
-
options?: AddOperationOptions
|
|
1573
|
+
options?: AddOperationOptions
|
|
1568
1574
|
): Promise<IOperationResult> {
|
|
1569
1575
|
return this.queueActions(drive, id, [action], options);
|
|
1570
1576
|
}
|
|
@@ -1573,7 +1579,7 @@ export class BaseDocumentDriveServer
|
|
|
1573
1579
|
drive: string,
|
|
1574
1580
|
id: string,
|
|
1575
1581
|
actions: Action[],
|
|
1576
|
-
options?: AddOperationOptions
|
|
1582
|
+
options?: AddOperationOptions
|
|
1577
1583
|
): Promise<IOperationResult> {
|
|
1578
1584
|
try {
|
|
1579
1585
|
const jobId = await this.queueManager.addJob({
|
|
@@ -1592,7 +1598,7 @@ export class BaseDocumentDriveServer
|
|
|
1592
1598
|
unsubscribeError();
|
|
1593
1599
|
resolve(result);
|
|
1594
1600
|
}
|
|
1595
|
-
}
|
|
1601
|
+
}
|
|
1596
1602
|
);
|
|
1597
1603
|
const unsubscribeError = this.queueManager.on(
|
|
1598
1604
|
"jobFailed",
|
|
@@ -1602,7 +1608,7 @@ export class BaseDocumentDriveServer
|
|
|
1602
1608
|
unsubscribeError();
|
|
1603
1609
|
reject(error);
|
|
1604
1610
|
}
|
|
1605
|
-
}
|
|
1611
|
+
}
|
|
1606
1612
|
);
|
|
1607
1613
|
});
|
|
1608
1614
|
} catch (error) {
|
|
@@ -1614,7 +1620,7 @@ export class BaseDocumentDriveServer
|
|
|
1614
1620
|
async queueDriveAction(
|
|
1615
1621
|
drive: string,
|
|
1616
1622
|
action: DocumentDriveAction | BaseAction,
|
|
1617
|
-
options?: AddOperationOptions
|
|
1623
|
+
options?: AddOperationOptions
|
|
1618
1624
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1619
1625
|
return this.queueDriveActions(drive, [action], options);
|
|
1620
1626
|
}
|
|
@@ -1622,7 +1628,7 @@ export class BaseDocumentDriveServer
|
|
|
1622
1628
|
async queueDriveActions(
|
|
1623
1629
|
drive: string,
|
|
1624
1630
|
actions: (DocumentDriveAction | BaseAction)[],
|
|
1625
|
-
options?: AddOperationOptions
|
|
1631
|
+
options?: AddOperationOptions
|
|
1626
1632
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1627
1633
|
try {
|
|
1628
1634
|
const jobId = await this.queueManager.addJob({
|
|
@@ -1640,7 +1646,7 @@ export class BaseDocumentDriveServer
|
|
|
1640
1646
|
unsubscribeError();
|
|
1641
1647
|
resolve(result as IOperationResult<DocumentDriveDocument>);
|
|
1642
1648
|
}
|
|
1643
|
-
}
|
|
1649
|
+
}
|
|
1644
1650
|
);
|
|
1645
1651
|
const unsubscribeError = this.queueManager.on(
|
|
1646
1652
|
"jobFailed",
|
|
@@ -1650,9 +1656,9 @@ export class BaseDocumentDriveServer
|
|
|
1650
1656
|
unsubscribeError();
|
|
1651
1657
|
reject(error);
|
|
1652
1658
|
}
|
|
1653
|
-
}
|
|
1659
|
+
}
|
|
1654
1660
|
);
|
|
1655
|
-
}
|
|
1661
|
+
}
|
|
1656
1662
|
);
|
|
1657
1663
|
} catch (error) {
|
|
1658
1664
|
logger.error("Error adding drive job", error);
|
|
@@ -1664,7 +1670,7 @@ export class BaseDocumentDriveServer
|
|
|
1664
1670
|
drive: string,
|
|
1665
1671
|
id: string,
|
|
1666
1672
|
operations: Operation[],
|
|
1667
|
-
options?: AddOperationOptions
|
|
1673
|
+
options?: AddOperationOptions
|
|
1668
1674
|
) {
|
|
1669
1675
|
// if operations are already stored then returns the result
|
|
1670
1676
|
const result = await this.resultIfExistingOperations(drive, id, operations);
|
|
@@ -1682,7 +1688,7 @@ export class BaseDocumentDriveServer
|
|
|
1682
1688
|
drive,
|
|
1683
1689
|
id,
|
|
1684
1690
|
documentStorage,
|
|
1685
|
-
operations
|
|
1691
|
+
operations
|
|
1686
1692
|
);
|
|
1687
1693
|
|
|
1688
1694
|
if (!result.document) {
|
|
@@ -1714,14 +1720,14 @@ export class BaseDocumentDriveServer
|
|
|
1714
1720
|
}
|
|
1715
1721
|
return acc;
|
|
1716
1722
|
},
|
|
1717
|
-
{ scopes: [] as string[], branches: ["main"] }
|
|
1723
|
+
{ scopes: [] as string[], branches: ["main"] }
|
|
1718
1724
|
);
|
|
1719
1725
|
|
|
1720
1726
|
const syncUnits = await this.getSynchronizationUnits(
|
|
1721
1727
|
drive,
|
|
1722
1728
|
[id],
|
|
1723
1729
|
scopes,
|
|
1724
|
-
branches
|
|
1730
|
+
branches
|
|
1725
1731
|
);
|
|
1726
1732
|
|
|
1727
1733
|
// checks if any of the provided operations where reshufled
|
|
@@ -1732,8 +1738,8 @@ export class BaseDocumentDriveServer
|
|
|
1732
1738
|
o.id === appliedOp.id &&
|
|
1733
1739
|
o.index === appliedOp.index &&
|
|
1734
1740
|
o.skip === appliedOp.skip &&
|
|
1735
|
-
o.hash === appliedOp.hash
|
|
1736
|
-
)
|
|
1741
|
+
o.hash === appliedOp.hash
|
|
1742
|
+
)
|
|
1737
1743
|
);
|
|
1738
1744
|
|
|
1739
1745
|
// if there are no new operations then reuses the provided source
|
|
@@ -1764,7 +1770,7 @@ export class BaseDocumentDriveServer
|
|
|
1764
1770
|
}
|
|
1765
1771
|
},
|
|
1766
1772
|
this.handleListenerError.bind(this),
|
|
1767
|
-
options?.forceSync ?? source.type === "local"
|
|
1773
|
+
options?.forceSync ?? source.type === "local"
|
|
1768
1774
|
)
|
|
1769
1775
|
.then((updates) => {
|
|
1770
1776
|
if (updates.length) {
|
|
@@ -1786,7 +1792,7 @@ export class BaseDocumentDriveServer
|
|
|
1786
1792
|
{
|
|
1787
1793
|
[operationSource]: "ERROR",
|
|
1788
1794
|
},
|
|
1789
|
-
error as Error
|
|
1795
|
+
error as Error
|
|
1790
1796
|
);
|
|
1791
1797
|
|
|
1792
1798
|
for (const syncUnit of syncUnits) {
|
|
@@ -1795,7 +1801,7 @@ export class BaseDocumentDriveServer
|
|
|
1795
1801
|
{
|
|
1796
1802
|
[operationSource]: "ERROR",
|
|
1797
1803
|
},
|
|
1798
|
-
error as Error
|
|
1804
|
+
error as Error
|
|
1799
1805
|
);
|
|
1800
1806
|
}
|
|
1801
1807
|
});
|
|
@@ -1820,7 +1826,7 @@ export class BaseDocumentDriveServer
|
|
|
1820
1826
|
"ERROR",
|
|
1821
1827
|
undefined,
|
|
1822
1828
|
(error as Error).message,
|
|
1823
|
-
(error as Error).cause
|
|
1829
|
+
(error as Error).cause
|
|
1824
1830
|
);
|
|
1825
1831
|
|
|
1826
1832
|
return {
|
|
@@ -1836,7 +1842,7 @@ export class BaseDocumentDriveServer
|
|
|
1836
1842
|
addDriveOperation(
|
|
1837
1843
|
drive: string,
|
|
1838
1844
|
operation: Operation<DocumentDriveAction | BaseAction>,
|
|
1839
|
-
options?: AddOperationOptions
|
|
1845
|
+
options?: AddOperationOptions
|
|
1840
1846
|
) {
|
|
1841
1847
|
return this.addDriveOperations(drive, [operation], options);
|
|
1842
1848
|
}
|
|
@@ -1854,7 +1860,7 @@ export class BaseDocumentDriveServer
|
|
|
1854
1860
|
callback: (document: DocumentDriveStorage) => Promise<{
|
|
1855
1861
|
operations: Operation<DocumentDriveAction | BaseAction>[];
|
|
1856
1862
|
header: DocumentHeader;
|
|
1857
|
-
}
|
|
1863
|
+
}>
|
|
1858
1864
|
) {
|
|
1859
1865
|
if (!this.storage.addDriveOperationsWithTransaction) {
|
|
1860
1866
|
const documentStorage = await this.storage.getDrive(drive);
|
|
@@ -1864,7 +1870,7 @@ export class BaseDocumentDriveServer
|
|
|
1864
1870
|
await this.storage.addDriveOperations(
|
|
1865
1871
|
drive,
|
|
1866
1872
|
result.operations,
|
|
1867
|
-
result.header
|
|
1873
|
+
result.header
|
|
1868
1874
|
);
|
|
1869
1875
|
}
|
|
1870
1876
|
return result;
|
|
@@ -1876,14 +1882,14 @@ export class BaseDocumentDriveServer
|
|
|
1876
1882
|
queueDriveOperation(
|
|
1877
1883
|
drive: string,
|
|
1878
1884
|
operation: Operation<DocumentDriveAction | BaseAction>,
|
|
1879
|
-
options?: AddOperationOptions
|
|
1885
|
+
options?: AddOperationOptions
|
|
1880
1886
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1881
1887
|
return this.queueDriveOperations(drive, [operation], options);
|
|
1882
1888
|
}
|
|
1883
1889
|
|
|
1884
1890
|
private async resultIfExistingDriveOperations(
|
|
1885
1891
|
driveId: string,
|
|
1886
|
-
operations: Operation<DocumentDriveAction | BaseAction>[]
|
|
1892
|
+
operations: Operation<DocumentDriveAction | BaseAction>[]
|
|
1887
1893
|
): Promise<IOperationResult<DocumentDriveDocument> | undefined> {
|
|
1888
1894
|
try {
|
|
1889
1895
|
const drive = await this.getDrive(driveId);
|
|
@@ -1895,8 +1901,8 @@ export class BaseDocumentDriveServer
|
|
|
1895
1901
|
existingOp.id === op.id &&
|
|
1896
1902
|
existingOp.index === op.index &&
|
|
1897
1903
|
existingOp.type === op.type &&
|
|
1898
|
-
existingOp.hash === op.hash
|
|
1899
|
-
)
|
|
1904
|
+
existingOp.hash === op.hash
|
|
1905
|
+
)
|
|
1900
1906
|
);
|
|
1901
1907
|
if (!newOperation) {
|
|
1902
1908
|
return {
|
|
@@ -1917,12 +1923,12 @@ export class BaseDocumentDriveServer
|
|
|
1917
1923
|
async queueDriveOperations(
|
|
1918
1924
|
drive: string,
|
|
1919
1925
|
operations: Operation<DocumentDriveAction | BaseAction>[],
|
|
1920
|
-
options?: AddOperationOptions
|
|
1926
|
+
options?: AddOperationOptions
|
|
1921
1927
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1922
1928
|
// if operations are already stored then returns cached document
|
|
1923
1929
|
const result = await this.resultIfExistingDriveOperations(
|
|
1924
1930
|
drive,
|
|
1925
|
-
operations
|
|
1931
|
+
operations
|
|
1926
1932
|
);
|
|
1927
1933
|
if (result) {
|
|
1928
1934
|
return result;
|
|
@@ -1943,7 +1949,7 @@ export class BaseDocumentDriveServer
|
|
|
1943
1949
|
unsubscribeError();
|
|
1944
1950
|
resolve(result as IOperationResult<DocumentDriveDocument>);
|
|
1945
1951
|
}
|
|
1946
|
-
}
|
|
1952
|
+
}
|
|
1947
1953
|
);
|
|
1948
1954
|
const unsubscribeError = this.queueManager.on(
|
|
1949
1955
|
"jobFailed",
|
|
@@ -1953,9 +1959,9 @@ export class BaseDocumentDriveServer
|
|
|
1953
1959
|
unsubscribeError();
|
|
1954
1960
|
reject(error);
|
|
1955
1961
|
}
|
|
1956
|
-
}
|
|
1962
|
+
}
|
|
1957
1963
|
);
|
|
1958
|
-
}
|
|
1964
|
+
}
|
|
1959
1965
|
);
|
|
1960
1966
|
} catch (error) {
|
|
1961
1967
|
logger.error("Error adding drive job", error);
|
|
@@ -1966,7 +1972,7 @@ export class BaseDocumentDriveServer
|
|
|
1966
1972
|
async addDriveOperations(
|
|
1967
1973
|
drive: string,
|
|
1968
1974
|
operations: Operation<DocumentDriveAction | BaseAction>[],
|
|
1969
|
-
options?: AddOperationOptions
|
|
1975
|
+
options?: AddOperationOptions
|
|
1970
1976
|
) {
|
|
1971
1977
|
let document: DocumentDriveDocument | undefined;
|
|
1972
1978
|
const operationsApplied: Operation<DocumentDriveAction | BaseAction>[] = [];
|
|
@@ -1976,7 +1982,7 @@ export class BaseDocumentDriveServer
|
|
|
1976
1982
|
// if operations are already stored then returns cached drive
|
|
1977
1983
|
const result = await this.resultIfExistingDriveOperations(
|
|
1978
1984
|
drive,
|
|
1979
|
-
operations
|
|
1985
|
+
operations
|
|
1980
1986
|
);
|
|
1981
1987
|
if (result) {
|
|
1982
1988
|
return result;
|
|
@@ -2033,8 +2039,8 @@ export class BaseDocumentDriveServer
|
|
|
2033
2039
|
o.id === appliedOp.id &&
|
|
2034
2040
|
o.index === appliedOp.index &&
|
|
2035
2041
|
o.skip === appliedOp.skip &&
|
|
2036
|
-
o.hash === appliedOp.hash
|
|
2037
|
-
)
|
|
2042
|
+
o.hash === appliedOp.hash
|
|
2043
|
+
)
|
|
2038
2044
|
);
|
|
2039
2045
|
|
|
2040
2046
|
// if there are no new operations then reuses the provided source
|
|
@@ -2068,7 +2074,7 @@ export class BaseDocumentDriveServer
|
|
|
2068
2074
|
});
|
|
2069
2075
|
},
|
|
2070
2076
|
this.handleListenerError.bind(this),
|
|
2071
|
-
options?.forceSync ?? source.type === "local"
|
|
2077
|
+
options?.forceSync ?? source.type === "local"
|
|
2072
2078
|
)
|
|
2073
2079
|
.then((updates) => {
|
|
2074
2080
|
if (updates.length) {
|
|
@@ -2082,7 +2088,7 @@ export class BaseDocumentDriveServer
|
|
|
2082
2088
|
this.updateSyncUnitStatus(
|
|
2083
2089
|
drive,
|
|
2084
2090
|
{ [operationSource]: "ERROR" },
|
|
2085
|
-
error as Error
|
|
2091
|
+
error as Error
|
|
2086
2092
|
);
|
|
2087
2093
|
});
|
|
2088
2094
|
}
|
|
@@ -2113,7 +2119,7 @@ export class BaseDocumentDriveServer
|
|
|
2113
2119
|
"ERROR",
|
|
2114
2120
|
undefined,
|
|
2115
2121
|
(error as Error).message,
|
|
2116
|
-
(error as Error).cause
|
|
2122
|
+
(error as Error).cause
|
|
2117
2123
|
);
|
|
2118
2124
|
|
|
2119
2125
|
return {
|
|
@@ -2128,7 +2134,7 @@ export class BaseDocumentDriveServer
|
|
|
2128
2134
|
|
|
2129
2135
|
private _buildOperations<T extends Action>(
|
|
2130
2136
|
document: Document,
|
|
2131
|
-
actions: (T | BaseAction)[]
|
|
2137
|
+
actions: (T | BaseAction)[]
|
|
2132
2138
|
): Operation<T | BaseAction>[] {
|
|
2133
2139
|
const operations: Operation<T | BaseAction>[] = [];
|
|
2134
2140
|
const { reducer } = this.getDocumentModel(document.documentType);
|
|
@@ -2147,7 +2153,7 @@ export class BaseDocumentDriveServer
|
|
|
2147
2153
|
drive: string,
|
|
2148
2154
|
id: string,
|
|
2149
2155
|
action: Action,
|
|
2150
|
-
options?: AddOperationOptions
|
|
2156
|
+
options?: AddOperationOptions
|
|
2151
2157
|
): Promise<IOperationResult> {
|
|
2152
2158
|
return this.addActions(drive, id, [action], options);
|
|
2153
2159
|
}
|
|
@@ -2156,7 +2162,7 @@ export class BaseDocumentDriveServer
|
|
|
2156
2162
|
drive: string,
|
|
2157
2163
|
id: string,
|
|
2158
2164
|
actions: Action[],
|
|
2159
|
-
options?: AddOperationOptions
|
|
2165
|
+
options?: AddOperationOptions
|
|
2160
2166
|
): Promise<IOperationResult> {
|
|
2161
2167
|
const document = await this.getDocument(drive, id);
|
|
2162
2168
|
const operations = this._buildOperations(document, actions);
|
|
@@ -2166,7 +2172,7 @@ export class BaseDocumentDriveServer
|
|
|
2166
2172
|
async addDriveAction(
|
|
2167
2173
|
drive: string,
|
|
2168
2174
|
action: DocumentDriveAction | BaseAction,
|
|
2169
|
-
options?: AddOperationOptions
|
|
2175
|
+
options?: AddOperationOptions
|
|
2170
2176
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
2171
2177
|
return this.addDriveActions(drive, [action], options);
|
|
2172
2178
|
}
|
|
@@ -2174,7 +2180,7 @@ export class BaseDocumentDriveServer
|
|
|
2174
2180
|
async addDriveActions(
|
|
2175
2181
|
drive: string,
|
|
2176
2182
|
actions: (DocumentDriveAction | BaseAction)[],
|
|
2177
|
-
options?: AddOperationOptions
|
|
2183
|
+
options?: AddOperationOptions
|
|
2178
2184
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
2179
2185
|
const document = await this.getDrive(drive);
|
|
2180
2186
|
const operations = this._buildOperations(document, actions);
|
|
@@ -2190,7 +2196,7 @@ export class BaseDocumentDriveServer
|
|
|
2190
2196
|
label: string;
|
|
2191
2197
|
block: boolean;
|
|
2192
2198
|
filter: ListenerFilter;
|
|
2193
|
-
}
|
|
2199
|
+
}
|
|
2194
2200
|
) {
|
|
2195
2201
|
const listener: AddListenerInput["listener"] = {
|
|
2196
2202
|
callInfo: {
|
|
@@ -2224,26 +2230,26 @@ export class BaseDocumentDriveServer
|
|
|
2224
2230
|
for (const listener of listeners) {
|
|
2225
2231
|
await this.addDriveAction(
|
|
2226
2232
|
driveId,
|
|
2227
|
-
actions.removeListener({ listenerId: listener.listenerId })
|
|
2233
|
+
actions.removeListener({ listenerId: listener.listenerId })
|
|
2228
2234
|
);
|
|
2229
2235
|
}
|
|
2230
2236
|
|
|
2231
2237
|
for (const trigger of triggers) {
|
|
2232
2238
|
await this.addDriveAction(
|
|
2233
2239
|
driveId,
|
|
2234
|
-
actions.removeTrigger({ triggerId: trigger.id })
|
|
2240
|
+
actions.removeTrigger({ triggerId: trigger.id })
|
|
2235
2241
|
);
|
|
2236
2242
|
}
|
|
2237
2243
|
|
|
2238
2244
|
await this.addDriveAction(
|
|
2239
2245
|
driveId,
|
|
2240
|
-
actions.setSharingType({ type: "LOCAL" })
|
|
2246
|
+
actions.setSharingType({ type: "LOCAL" })
|
|
2241
2247
|
);
|
|
2242
2248
|
}
|
|
2243
2249
|
|
|
2244
2250
|
private async addListener(
|
|
2245
2251
|
driveId: string,
|
|
2246
|
-
operation: Operation<Action<"ADD_LISTENER", AddListenerInput
|
|
2252
|
+
operation: Operation<Action<"ADD_LISTENER", AddListenerInput>>
|
|
2247
2253
|
) {
|
|
2248
2254
|
const { listener } = operation.input;
|
|
2249
2255
|
await this.listenerStateManager.addListener({
|
|
@@ -2267,7 +2273,7 @@ export class BaseDocumentDriveServer
|
|
|
2267
2273
|
|
|
2268
2274
|
private async removeListener(
|
|
2269
2275
|
driveId: string,
|
|
2270
|
-
operation: Operation<Action<"REMOVE_LISTENER", RemoveListenerInput
|
|
2276
|
+
operation: Operation<Action<"REMOVE_LISTENER", RemoveListenerInput>>
|
|
2271
2277
|
) {
|
|
2272
2278
|
const { listenerId } = operation.input;
|
|
2273
2279
|
await this.listenerStateManager.removeListener(driveId, listenerId);
|
|
@@ -2275,26 +2281,26 @@ export class BaseDocumentDriveServer
|
|
|
2275
2281
|
|
|
2276
2282
|
getTransmitter(
|
|
2277
2283
|
driveId: string,
|
|
2278
|
-
listenerId: string
|
|
2284
|
+
listenerId: string
|
|
2279
2285
|
): Promise<ITransmitter | undefined> {
|
|
2280
2286
|
return this.listenerStateManager.getTransmitter(driveId, listenerId);
|
|
2281
2287
|
}
|
|
2282
2288
|
|
|
2283
2289
|
getListener(
|
|
2284
2290
|
driveId: string,
|
|
2285
|
-
listenerId: string
|
|
2291
|
+
listenerId: string
|
|
2286
2292
|
): Promise<ListenerState | undefined> {
|
|
2287
2293
|
return this.listenerStateManager.getListener(driveId, listenerId);
|
|
2288
2294
|
}
|
|
2289
2295
|
|
|
2290
2296
|
getSyncStatus(
|
|
2291
|
-
syncUnitId: string
|
|
2297
|
+
syncUnitId: string
|
|
2292
2298
|
): SyncStatus | SynchronizationUnitNotFoundError {
|
|
2293
2299
|
const status = this.syncStatus.get(syncUnitId);
|
|
2294
2300
|
if (!status) {
|
|
2295
2301
|
return new SynchronizationUnitNotFoundError(
|
|
2296
2302
|
`Sync status not found for syncUnitId: ${syncUnitId}`,
|
|
2297
|
-
syncUnitId
|
|
2303
|
+
syncUnitId
|
|
2298
2304
|
);
|
|
2299
2305
|
}
|
|
2300
2306
|
return this.getCombinedSyncUnitStatus(status);
|
|
@@ -2308,7 +2314,6 @@ export class BaseDocumentDriveServer
|
|
|
2308
2314
|
event: K,
|
|
2309
2315
|
...args: Parameters<DriveEvents[K]>
|
|
2310
2316
|
): void {
|
|
2311
|
-
logger.debug(`Emitting event ${event}`, args);
|
|
2312
2317
|
return this.emitter.emit(event, ...args);
|
|
2313
2318
|
}
|
|
2314
2319
|
}
|