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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "document-drive",
3
- "version": "1.0.0-alpha.44",
3
+ "version": "1.0.0-alpha.46",
4
4
  "license": "AGPL-3.0-only",
5
5
  "type": "module",
6
6
  "module": "./src/index.ts",
@@ -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
- strand.driveId,
131
- operations as Operation<DocumentDriveAction | BaseAction>[],
132
- false
133
- )
130
+ strand.driveId,
131
+ operations as Operation<DocumentDriveAction | BaseAction>[],
132
+ false
133
+ )
134
134
  : this.addOperations(
135
- strand.driveId,
136
- strand.documentId,
137
- operations,
138
- false
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 !== "undefined") {
233
+ if (typeof window !== 'undefined') {
230
234
  window.addEventListener('online', () => {
231
- this.listenerStateManager.triggerUpdate(false,
232
- this.handleListenerError.bind(this)).catch(error => {
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
- unit =>
302
- (!scope?.length ||
303
- scope.includes(unit.scope) ||
304
- scope.includes('*')) &&
305
- (!branch?.length ||
306
- branch.includes(unit.branch) ||
307
- branch.includes('*'))
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 = document.operations[scope as OperationScope] ?? [];
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("drives", drive);
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.setDocument("drives", drive, document).catch(logger.error);
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
- 'ERROR',
658
- nextOperation,
659
- (e as Error).message,
660
- (e as Error).cause
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
- 'ERROR',
922
- undefined,
923
- (error as Error).message,
924
- (error as Error).cause
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.setDocument("drives", drive, document).catch(logger.error);
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
- 'ERROR',
1092
- undefined,
1093
- (error as Error).message,
1094
- (error as Error).cause
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.index === historyOperation.index &&
487
- newOperation.skip === historyOperation.skip &&
488
- newOperation.scope === historyOperation.scope &&
489
- newOperation.hash === historyOperation.hash &&
490
- newOperation.type === historyOperation.type
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
  });