document-drive 1.0.0-alpha.44 → 1.0.0-alpha.46
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 +1 -1
- package/src/server/index.ts +61 -49
- package/src/utils/document-helpers.ts +8 -5
package/package.json
CHANGED
package/src/server/index.ts
CHANGED
|
@@ -22,6 +22,8 @@ import {
|
|
|
22
22
|
OperationScope
|
|
23
23
|
} from 'document-model/document';
|
|
24
24
|
import { createNanoEvents, Unsubscribe } from 'nanoevents';
|
|
25
|
+
import { ICache } from '../cache';
|
|
26
|
+
import InMemoryCache from '../cache/memory';
|
|
25
27
|
import { MemoryStorage } from '../storage/memory';
|
|
26
28
|
import type {
|
|
27
29
|
DocumentDriveStorage,
|
|
@@ -66,8 +68,6 @@ import {
|
|
|
66
68
|
type SynchronizationUnit
|
|
67
69
|
} from './types';
|
|
68
70
|
import { filterOperationsByRevision } from './utils';
|
|
69
|
-
import { ICache } from '../cache';
|
|
70
|
-
import InMemoryCache from '../cache/memory';
|
|
71
71
|
|
|
72
72
|
export * from './listener';
|
|
73
73
|
export type * from './types';
|
|
@@ -127,16 +127,16 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
|
|
|
127
127
|
|
|
128
128
|
const result = await (!strand.documentId
|
|
129
129
|
? this.addDriveOperations(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
130
|
+
strand.driveId,
|
|
131
|
+
operations as Operation<DocumentDriveAction | BaseAction>[],
|
|
132
|
+
false
|
|
133
|
+
)
|
|
134
134
|
: this.addOperations(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
135
|
+
strand.driveId,
|
|
136
|
+
strand.documentId,
|
|
137
|
+
operations,
|
|
138
|
+
false
|
|
139
|
+
));
|
|
140
140
|
|
|
141
141
|
if (result.status === 'ERROR') {
|
|
142
142
|
this.updateSyncStatus(strand.driveId, result.status, result.error);
|
|
@@ -219,25 +219,31 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
|
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
async initialize() {
|
|
222
|
+
const errors: Error[] = [];
|
|
222
223
|
const drives = await this.getDrives();
|
|
223
224
|
for (const drive of drives) {
|
|
224
|
-
await this._initializeDrive(drive)
|
|
225
|
+
await this._initializeDrive(drive).catch(error => {
|
|
226
|
+
logger.error(`Error initializing drive ${drive}`, error);
|
|
227
|
+
errors.push(error as Error);
|
|
228
|
+
});
|
|
225
229
|
}
|
|
226
230
|
|
|
227
231
|
// if network connect comes online then
|
|
228
232
|
// triggers the listeners update
|
|
229
|
-
if (typeof window !==
|
|
233
|
+
if (typeof window !== 'undefined') {
|
|
230
234
|
window.addEventListener('online', () => {
|
|
231
|
-
this.listenerStateManager
|
|
232
|
-
this.handleListenerError.bind(this))
|
|
235
|
+
this.listenerStateManager
|
|
236
|
+
.triggerUpdate(false, this.handleListenerError.bind(this))
|
|
237
|
+
.catch(error => {
|
|
233
238
|
logger.error(
|
|
234
239
|
'Non handled error updating listeners',
|
|
235
240
|
error
|
|
236
241
|
);
|
|
237
242
|
});
|
|
238
|
-
|
|
239
243
|
});
|
|
240
244
|
}
|
|
245
|
+
|
|
246
|
+
return errors.length === 0 ? null : errors;
|
|
241
247
|
}
|
|
242
248
|
|
|
243
249
|
private async _initializeDrive(driveId: string) {
|
|
@@ -298,14 +304,14 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
|
|
|
298
304
|
const nodeUnits =
|
|
299
305
|
scope?.length || branch?.length
|
|
300
306
|
? node.synchronizationUnits.filter(
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
307
|
+
unit =>
|
|
308
|
+
(!scope?.length ||
|
|
309
|
+
scope.includes(unit.scope) ||
|
|
310
|
+
scope.includes('*')) &&
|
|
311
|
+
(!branch?.length ||
|
|
312
|
+
branch.includes(unit.branch) ||
|
|
313
|
+
branch.includes('*'))
|
|
314
|
+
)
|
|
309
315
|
: node.synchronizationUnits;
|
|
310
316
|
if (!nodeUnits.length) {
|
|
311
317
|
continue;
|
|
@@ -316,7 +322,8 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
|
|
|
316
322
|
: this.getDrive(driveId));
|
|
317
323
|
|
|
318
324
|
for (const { syncId, scope, branch } of nodeUnits) {
|
|
319
|
-
const operations =
|
|
325
|
+
const operations =
|
|
326
|
+
document.operations[scope as OperationScope] ?? [];
|
|
320
327
|
const lastOperation = operations[operations.length - 1];
|
|
321
328
|
synchronizationUnits.push({
|
|
322
329
|
syncId,
|
|
@@ -483,7 +490,7 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
|
|
|
483
490
|
|
|
484
491
|
async getDrive(drive: string, options?: GetDocumentOptions) {
|
|
485
492
|
try {
|
|
486
|
-
const document = await this.cache.getDocument(
|
|
493
|
+
const document = await this.cache.getDocument('drives', drive);
|
|
487
494
|
if (document && isDocumentDrive(document)) {
|
|
488
495
|
return document;
|
|
489
496
|
}
|
|
@@ -509,7 +516,9 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
|
|
|
509
516
|
`Document with id ${drive} is not a Document Drive`
|
|
510
517
|
);
|
|
511
518
|
} else {
|
|
512
|
-
this.cache
|
|
519
|
+
this.cache
|
|
520
|
+
.setDocument('drives', drive, document)
|
|
521
|
+
.catch(logger.error);
|
|
513
522
|
return document;
|
|
514
523
|
}
|
|
515
524
|
}
|
|
@@ -591,6 +600,11 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
|
|
|
591
600
|
storageDocumentOperations
|
|
592
601
|
);
|
|
593
602
|
|
|
603
|
+
// No operations to apply
|
|
604
|
+
if (branch.length < 1) {
|
|
605
|
+
continue;
|
|
606
|
+
}
|
|
607
|
+
|
|
594
608
|
const trunk = garbageCollect(
|
|
595
609
|
sortOperations(storageDocumentOperations)
|
|
596
610
|
);
|
|
@@ -654,11 +668,11 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
|
|
|
654
668
|
e instanceof OperationError
|
|
655
669
|
? e
|
|
656
670
|
: new OperationError(
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
671
|
+
'ERROR',
|
|
672
|
+
nextOperation,
|
|
673
|
+
(e as Error).message,
|
|
674
|
+
(e as Error).cause
|
|
675
|
+
);
|
|
662
676
|
|
|
663
677
|
// TODO: don't break on errors...
|
|
664
678
|
break;
|
|
@@ -698,9 +712,7 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
|
|
|
698
712
|
operation: Operation,
|
|
699
713
|
skipHashValidation = false
|
|
700
714
|
) {
|
|
701
|
-
const documentModel = this._getDocumentModel(
|
|
702
|
-
document.documentType
|
|
703
|
-
);
|
|
715
|
+
const documentModel = this._getDocumentModel(document.documentType);
|
|
704
716
|
|
|
705
717
|
const signalResults: SignalResult[] = [];
|
|
706
718
|
let newDocument = document;
|
|
@@ -918,11 +930,11 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
|
|
|
918
930
|
error instanceof OperationError
|
|
919
931
|
? error
|
|
920
932
|
: new OperationError(
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
933
|
+
'ERROR',
|
|
934
|
+
undefined,
|
|
935
|
+
(error as Error).message,
|
|
936
|
+
(error as Error).cause
|
|
937
|
+
);
|
|
926
938
|
|
|
927
939
|
return {
|
|
928
940
|
status: operationError.status,
|
|
@@ -1011,7 +1023,9 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
|
|
|
1011
1023
|
throw error ?? new Error('Invalid Document Drive document');
|
|
1012
1024
|
}
|
|
1013
1025
|
|
|
1014
|
-
this.cache
|
|
1026
|
+
this.cache
|
|
1027
|
+
.setDocument('drives', drive, document)
|
|
1028
|
+
.catch(logger.error);
|
|
1015
1029
|
|
|
1016
1030
|
for (const operation of operationsApplied) {
|
|
1017
1031
|
switch (operation.type) {
|
|
@@ -1088,11 +1102,11 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
|
|
|
1088
1102
|
error instanceof OperationError
|
|
1089
1103
|
? error
|
|
1090
1104
|
: new OperationError(
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1105
|
+
'ERROR',
|
|
1106
|
+
undefined,
|
|
1107
|
+
(error as Error).message,
|
|
1108
|
+
(error as Error).cause
|
|
1109
|
+
);
|
|
1096
1110
|
|
|
1097
1111
|
return {
|
|
1098
1112
|
status: operationError.status,
|
|
@@ -1109,9 +1123,7 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
|
|
|
1109
1123
|
actions: (T | BaseAction)[]
|
|
1110
1124
|
): Operation<T | BaseAction>[] {
|
|
1111
1125
|
const operations: Operation<T | BaseAction>[] = [];
|
|
1112
|
-
const { reducer } = this._getDocumentModel(
|
|
1113
|
-
document.documentType
|
|
1114
|
-
);
|
|
1126
|
+
const { reducer } = this._getDocumentModel(document.documentType);
|
|
1115
1127
|
for (const action of actions) {
|
|
1116
1128
|
document = reducer(document, action);
|
|
1117
1129
|
const operation = document.operations[action.scope].slice().pop();
|
|
@@ -483,11 +483,14 @@ export function removeExistingOperations(
|
|
|
483
483
|
return newOperations.filter(newOperation => {
|
|
484
484
|
return !operationsHistory.some(historyOperation => {
|
|
485
485
|
return (
|
|
486
|
-
newOperation.
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
newOperation.
|
|
490
|
-
|
|
486
|
+
(newOperation.type === 'NOOP' &&
|
|
487
|
+
newOperation.skip === 0 &&
|
|
488
|
+
newOperation.index === historyOperation.index) ||
|
|
489
|
+
(newOperation.index === historyOperation.index &&
|
|
490
|
+
newOperation.skip === historyOperation.skip &&
|
|
491
|
+
newOperation.scope === historyOperation.scope &&
|
|
492
|
+
newOperation.hash === historyOperation.hash &&
|
|
493
|
+
newOperation.type === historyOperation.type)
|
|
491
494
|
);
|
|
492
495
|
});
|
|
493
496
|
});
|