document-drive 1.0.0-alpha.34 → 1.0.0-alpha.36

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.34",
3
+ "version": "1.0.0-alpha.36",
4
4
  "license": "AGPL-3.0-only",
5
5
  "type": "module",
6
6
  "module": "./src/index.ts",
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "peerDependencies": {
33
33
  "@prisma/client": "5.11.0",
34
- "document-model": "^1.0.35",
34
+ "document-model": "^1.0.41",
35
35
  "document-model-libs": "^1.18.1",
36
36
  "localforage": "^1.10.0",
37
37
  "sequelize": "^6.35.2",
@@ -55,7 +55,7 @@
55
55
  "@typescript-eslint/eslint-plugin": "^6.21.0",
56
56
  "@typescript-eslint/parser": "^6.21.0",
57
57
  "@vitest/coverage-v8": "^1.4.0",
58
- "document-model": "^1.0.36",
58
+ "document-model": "^1.0.41",
59
59
  "document-model-libs": "^1.24.0",
60
60
  "eslint": "^8.57.0",
61
61
  "eslint-config-prettier": "^9.1.0",
@@ -36,7 +36,7 @@ import {
36
36
  merge,
37
37
  precedes,
38
38
  removeExistingOperations,
39
- reshuffleByTimestampAndIndex,
39
+ reshuffleByTimestamp,
40
40
  sortOperations
41
41
  } from '../utils/document-helpers';
42
42
  import { requestPublicDrive } from '../utils/graphql';
@@ -557,7 +557,7 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
557
557
  const newHistory =
558
558
  tail.length < 1
559
559
  ? invertedTrunk
560
- : merge(trunk, invertedTrunk, reshuffleByTimestampAndIndex);
560
+ : merge(trunk, invertedTrunk, reshuffleByTimestamp);
561
561
 
562
562
  const lastOriginalOperation = trunk[trunk.length - 1];
563
563
 
@@ -581,11 +581,23 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
581
581
  }
582
582
 
583
583
  for (const nextOperation of newOperations) {
584
+ let skipHashValidation = false;
585
+
586
+ // when dealing with a merge (tail.length > 0) we have to skip hash validation
587
+ // for the operations that were re-indexed (previous hash becomes invalid due the new position in the history)
588
+ if (tail.length > 0) {
589
+ skipHashValidation = [...invertedTrunk, ...tail].some(
590
+ invertedTrunkOp =>
591
+ invertedTrunkOp.hash === nextOperation.hash
592
+ );
593
+ }
594
+
584
595
  try {
585
596
  const appliedResult = await this._performOperation<T, A>(
586
597
  drive,
587
598
  document,
588
- nextOperation
599
+ nextOperation,
600
+ skipHashValidation
589
601
  );
590
602
  document = appliedResult.document;
591
603
  signals.push(...appliedResult.signals);
@@ -639,7 +651,8 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
639
651
  private async _performOperation<T extends Document, A extends Action>(
640
652
  drive: string,
641
653
  documentStorage: DocumentStorage<T>,
642
- operation: Operation<A | BaseAction>
654
+ operation: Operation<A | BaseAction>,
655
+ skipHashValidation = false
643
656
  ) {
644
657
  const documentModel = this._getDocumentModel(
645
658
  documentStorage.documentType
@@ -700,7 +713,8 @@ export class DocumentDriveServer extends BaseDocumentDriveServer {
700
713
  );
701
714
  } else if (
702
715
  operation.type !== 'NOOP' &&
703
- appliedOperation[0]!.hash !== operation.hash
716
+ appliedOperation[0]!.hash !== operation.hash &&
717
+ !skipHashValidation
704
718
  ) {
705
719
  throw new OperationError(
706
720
  'CONFLICT',
@@ -15,10 +15,10 @@ export class BrowserStorage implements IDriveStorage {
15
15
  static SEP = ':';
16
16
  static DRIVES_KEY = 'DRIVES';
17
17
 
18
- constructor() {
18
+ constructor(namespace?: string) {
19
19
  this.db = import('localforage').then(localForage =>
20
20
  localForage.default.createInstance({
21
- name: BrowserStorage.DBName
21
+ name: namespace ? `${namespace}:${BrowserStorage.DBName}` : BrowserStorage.DBName
22
22
  })
23
23
  );
24
24
  }