document-drive 1.9.0 → 1.10.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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "document-drive",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./src/index.ts",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"uuid": "^9.0.1",
|
|
36
36
|
"@powerhousedao/scalars": "1.13.0",
|
|
37
37
|
"document-model": "2.11.0",
|
|
38
|
-
"document-model-libs": "1.121.
|
|
38
|
+
"document-model-libs": "1.121.1"
|
|
39
39
|
},
|
|
40
40
|
"optionalDependencies": {
|
|
41
41
|
"@prisma/client": "^5.18.0",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"sanitize-filename": "^1.6.3",
|
|
68
68
|
"uuid": "^9.0.1",
|
|
69
69
|
"document-model": "2.11.0",
|
|
70
|
-
"document-model-libs": "1.121.
|
|
70
|
+
"document-model-libs": "1.121.1"
|
|
71
71
|
},
|
|
72
72
|
"scripts": {
|
|
73
73
|
"check-types": "tsc --build",
|
package/src/server/index.ts
CHANGED
|
@@ -100,7 +100,7 @@ import {
|
|
|
100
100
|
type SignalResult,
|
|
101
101
|
type SynchronizationUnit,
|
|
102
102
|
} from "./types";
|
|
103
|
-
import { filterOperationsByRevision } from "./utils";
|
|
103
|
+
import { filterOperationsByRevision, isAtRevision } from "./utils";
|
|
104
104
|
|
|
105
105
|
export * from "./listener";
|
|
106
106
|
export type * from "./types";
|
|
@@ -1000,21 +1000,27 @@ export class BaseDocumentDriveServer
|
|
|
1000
1000
|
}
|
|
1001
1001
|
|
|
1002
1002
|
async getDrive(drive: string, options?: GetDocumentOptions) {
|
|
1003
|
+
let document: DocumentDriveDocument | undefined;
|
|
1003
1004
|
try {
|
|
1004
|
-
const
|
|
1005
|
-
if (
|
|
1006
|
-
|
|
1005
|
+
const cachedDocument = await this.cache.getDocument("drives", drive); // TODO support GetDocumentOptions
|
|
1006
|
+
if (cachedDocument && isDocumentDrive(cachedDocument)) {
|
|
1007
|
+
document = cachedDocument;
|
|
1008
|
+
if (isAtRevision(document, options?.revisions)) {
|
|
1009
|
+
return document;
|
|
1010
|
+
}
|
|
1007
1011
|
}
|
|
1008
1012
|
} catch (e) {
|
|
1009
1013
|
logger.error("Error getting drive from cache", e);
|
|
1010
1014
|
}
|
|
1011
|
-
const driveStorage = await this.storage.getDrive(drive);
|
|
1012
|
-
const
|
|
1013
|
-
if (!isDocumentDrive(
|
|
1015
|
+
const driveStorage = document ?? (await this.storage.getDrive(drive));
|
|
1016
|
+
const result = this._buildDocument(driveStorage, options);
|
|
1017
|
+
if (!isDocumentDrive(result)) {
|
|
1014
1018
|
throw new Error(`Document with id ${drive} is not a Document Drive`);
|
|
1015
1019
|
} else {
|
|
1016
|
-
|
|
1017
|
-
|
|
1020
|
+
if (!options?.revisions) {
|
|
1021
|
+
this.cache.setDocument("drives", drive, result).catch(logger.error);
|
|
1022
|
+
}
|
|
1023
|
+
return result;
|
|
1018
1024
|
}
|
|
1019
1025
|
}
|
|
1020
1026
|
|
|
@@ -1039,18 +1045,22 @@ export class BaseDocumentDriveServer
|
|
|
1039
1045
|
}
|
|
1040
1046
|
|
|
1041
1047
|
async getDocument(drive: string, id: string, options?: GetDocumentOptions) {
|
|
1048
|
+
let cachedDocument: Document | undefined;
|
|
1042
1049
|
try {
|
|
1043
|
-
|
|
1044
|
-
if (
|
|
1045
|
-
return
|
|
1050
|
+
cachedDocument = await this.cache.getDocument(drive, id); // TODO support GetDocumentOptions
|
|
1051
|
+
if (cachedDocument && isAtRevision(cachedDocument, options?.revisions)) {
|
|
1052
|
+
return cachedDocument;
|
|
1046
1053
|
}
|
|
1047
1054
|
} catch (e) {
|
|
1048
1055
|
logger.error("Error getting document from cache", e);
|
|
1049
1056
|
}
|
|
1050
|
-
const documentStorage =
|
|
1057
|
+
const documentStorage =
|
|
1058
|
+
cachedDocument ?? (await this.storage.getDocument(drive, id));
|
|
1051
1059
|
const document = this._buildDocument(documentStorage, options);
|
|
1052
1060
|
|
|
1053
|
-
|
|
1061
|
+
if (!options?.revisions) {
|
|
1062
|
+
this.cache.setDocument(drive, id, document).catch(logger.error);
|
|
1063
|
+
}
|
|
1054
1064
|
return document;
|
|
1055
1065
|
}
|
|
1056
1066
|
|
|
@@ -1293,7 +1303,11 @@ export class BaseDocumentDriveServer
|
|
|
1293
1303
|
documentStorage: DocumentStorage<T>,
|
|
1294
1304
|
options?: GetDocumentOptions,
|
|
1295
1305
|
): T {
|
|
1296
|
-
if (
|
|
1306
|
+
if (
|
|
1307
|
+
documentStorage.state &&
|
|
1308
|
+
(!options || options.checkHashes === false) &&
|
|
1309
|
+
isAtRevision(documentStorage as unknown as Document, options?.revisions)
|
|
1310
|
+
) {
|
|
1297
1311
|
return documentStorage as T;
|
|
1298
1312
|
}
|
|
1299
1313
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Document, Operation, OperationScope } from "document-model/document";
|
|
2
2
|
import { logger } from "../../../utils/logger";
|
|
3
3
|
import {
|
|
4
|
+
GetDocumentOptions,
|
|
4
5
|
IBaseDocumentDriveServer,
|
|
5
6
|
Listener,
|
|
6
7
|
ListenerRevision,
|
|
@@ -59,16 +60,21 @@ export class InternalTransmitter implements ITransmitter {
|
|
|
59
60
|
if (state) {
|
|
60
61
|
return state;
|
|
61
62
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
revisions: {
|
|
67
|
-
[strand.scope]: index,
|
|
68
|
-
},
|
|
69
|
-
checkHashes: false,
|
|
63
|
+
|
|
64
|
+
const getDocumentOptions: GetDocumentOptions = {
|
|
65
|
+
revisions: {
|
|
66
|
+
[strand.scope]: index,
|
|
70
67
|
},
|
|
71
|
-
|
|
68
|
+
checkHashes: false,
|
|
69
|
+
};
|
|
70
|
+
const document = await (strand.documentId
|
|
71
|
+
? this.drive.getDocument(
|
|
72
|
+
strand.driveId,
|
|
73
|
+
strand.documentId,
|
|
74
|
+
getDocumentOptions,
|
|
75
|
+
)
|
|
76
|
+
: this.drive.getDrive(strand.driveId, getDocumentOptions));
|
|
77
|
+
|
|
72
78
|
if (index < 0) {
|
|
73
79
|
stateByIndex.set(index, document.initialState.state[strand.scope]);
|
|
74
80
|
} else {
|
package/src/server/utils.ts
CHANGED
|
@@ -15,6 +15,18 @@ export function buildRevisionsFilter(
|
|
|
15
15
|
}, {});
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
export function buildDocumentRevisionsFilter(
|
|
19
|
+
document: Document,
|
|
20
|
+
): RevisionsFilter {
|
|
21
|
+
return Object.entries(document.operations).reduce<RevisionsFilter>(
|
|
22
|
+
(acc, [scope, operations]) => {
|
|
23
|
+
acc[scope as OperationScope] = operations.at(-1)?.index ?? -1;
|
|
24
|
+
return acc;
|
|
25
|
+
},
|
|
26
|
+
{} as RevisionsFilter,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
18
30
|
export function filterOperationsByRevision(
|
|
19
31
|
operations: Document["operations"],
|
|
20
32
|
revisions?: RevisionsFilter,
|
|
@@ -24,11 +36,47 @@ export function filterOperationsByRevision(
|
|
|
24
36
|
}
|
|
25
37
|
return (Object.keys(operations) as OperationScope[]).reduce<
|
|
26
38
|
Document["operations"]
|
|
27
|
-
>(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
>(
|
|
40
|
+
(acc, scope) => {
|
|
41
|
+
const revision = revisions[scope];
|
|
42
|
+
if (revision !== undefined) {
|
|
43
|
+
acc[scope] = operations[scope].filter((op) => op.index <= revision);
|
|
44
|
+
}
|
|
45
|
+
return acc;
|
|
46
|
+
},
|
|
47
|
+
{ global: [], local: [] } as unknown as Document["operations"],
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function isAtRevision(
|
|
52
|
+
document: Document,
|
|
53
|
+
revisions?: RevisionsFilter,
|
|
54
|
+
): boolean {
|
|
55
|
+
return (
|
|
56
|
+
!revisions ||
|
|
57
|
+
Object.entries(revisions).find(([scope, revision]) => {
|
|
58
|
+
const operation = document.operations[scope as OperationScope].at(-1);
|
|
59
|
+
if (revision === -1) {
|
|
60
|
+
return operation !== undefined;
|
|
61
|
+
}
|
|
62
|
+
return operation?.index !== revision;
|
|
63
|
+
}) === undefined
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function isAfterRevision(
|
|
68
|
+
document: Document,
|
|
69
|
+
revisions?: RevisionsFilter,
|
|
70
|
+
): boolean {
|
|
71
|
+
return (
|
|
72
|
+
!revisions ||
|
|
73
|
+
Object.entries(revisions).every(([scope, revision]) => {
|
|
74
|
+
const operation = document.operations[scope as OperationScope].at(-1);
|
|
75
|
+
|
|
76
|
+
if (revision === -1) {
|
|
77
|
+
return operation !== undefined;
|
|
78
|
+
}
|
|
79
|
+
return operation && operation.index > revision;
|
|
80
|
+
})
|
|
81
|
+
);
|
|
34
82
|
}
|