document-drive 1.17.2 → 1.18.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/README.md +83 -0
- package/package.json +11 -9
- package/src/server/index.ts +325 -232
- package/src/server/listener/manager.ts +136 -126
- package/src/server/listener/transmitter/pull-responder.ts +4 -11
- package/src/server/listener/transmitter/switchboard-push.ts +3 -12
- package/src/server/types.ts +114 -144
package/src/server/index.ts
CHANGED
|
@@ -68,7 +68,7 @@ import {
|
|
|
68
68
|
OperationError,
|
|
69
69
|
SynchronizationUnitNotFoundError,
|
|
70
70
|
} from "./error";
|
|
71
|
-
import { ListenerManager } from "./listener
|
|
71
|
+
import { ListenerManager } from "./listener";
|
|
72
72
|
import {
|
|
73
73
|
CancelPullLoop,
|
|
74
74
|
InternalTransmitter,
|
|
@@ -76,9 +76,9 @@ import {
|
|
|
76
76
|
ITransmitter,
|
|
77
77
|
PullResponderTransmitter,
|
|
78
78
|
StrandUpdateSource,
|
|
79
|
+
SwitchboardPushTransmitter,
|
|
79
80
|
} from "./listener/transmitter";
|
|
80
81
|
import {
|
|
81
|
-
AbstractDocumentDriveServer,
|
|
82
82
|
AddOperationOptions,
|
|
83
83
|
DefaultListenerManagerOptions,
|
|
84
84
|
DocumentDriveServerOptions,
|
|
@@ -86,7 +86,9 @@ import {
|
|
|
86
86
|
GetDocumentOptions,
|
|
87
87
|
GetStrandsOptions,
|
|
88
88
|
IBaseDocumentDriveServer,
|
|
89
|
+
IListenerManager,
|
|
89
90
|
IOperationResult,
|
|
91
|
+
Listener,
|
|
90
92
|
ListenerState,
|
|
91
93
|
RemoteDriveAccessLevel,
|
|
92
94
|
RemoteDriveOptions,
|
|
@@ -109,15 +111,47 @@ export * from "../read-mode";
|
|
|
109
111
|
|
|
110
112
|
export const PULL_DRIVE_INTERVAL = 5000;
|
|
111
113
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
interface ITransmitterFactory {
|
|
115
|
+
instance(
|
|
116
|
+
transmitterType: string,
|
|
117
|
+
listener: Listener,
|
|
118
|
+
driveServer: IBaseDocumentDriveServer,
|
|
119
|
+
): ITransmitter;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export class TransmitterFactory implements ITransmitterFactory {
|
|
123
|
+
private readonly listenerManager: IListenerManager;
|
|
124
|
+
|
|
125
|
+
constructor(listenerManager: IListenerManager) {
|
|
126
|
+
this.listenerManager = listenerManager;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
instance(
|
|
130
|
+
transmitterType: string,
|
|
131
|
+
listener: Listener,
|
|
132
|
+
driveServer: IBaseDocumentDriveServer,
|
|
133
|
+
): ITransmitter {
|
|
134
|
+
switch (transmitterType) {
|
|
135
|
+
case "SwitchboardPush": {
|
|
136
|
+
return new SwitchboardPushTransmitter(listener.callInfo!.data!);
|
|
137
|
+
}
|
|
138
|
+
case "Internal": {
|
|
139
|
+
return new InternalTransmitter(listener, driveServer);
|
|
140
|
+
}
|
|
141
|
+
default: {
|
|
142
|
+
return new PullResponderTransmitter(listener, this.listenerManager);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export class BaseDocumentDriveServer implements IBaseDocumentDriveServer {
|
|
116
149
|
private emitter = createNanoEvents<DriveEvents>();
|
|
117
150
|
private cache: ICache;
|
|
118
151
|
private documentModels: DocumentModel[];
|
|
119
152
|
private storage: IDriveStorage;
|
|
120
|
-
private
|
|
153
|
+
private transmitterFactory: ITransmitterFactory;
|
|
154
|
+
private listenerManager: IListenerManager;
|
|
121
155
|
private triggerMap = new Map<
|
|
122
156
|
DocumentDriveState["id"],
|
|
123
157
|
Map<Trigger["id"], CancelPullLoop>
|
|
@@ -138,7 +172,6 @@ export class BaseDocumentDriveServer
|
|
|
138
172
|
queueManager: IQueueManager = new BaseQueueManager(),
|
|
139
173
|
options?: DocumentDriveServerOptions,
|
|
140
174
|
) {
|
|
141
|
-
super();
|
|
142
175
|
this.options = {
|
|
143
176
|
...options,
|
|
144
177
|
defaultDrives: {
|
|
@@ -154,11 +187,16 @@ export class BaseDocumentDriveServer
|
|
|
154
187
|
: options.taskQueueMethod,
|
|
155
188
|
};
|
|
156
189
|
|
|
157
|
-
this
|
|
190
|
+
// todo: pull this into the constructor -- there is a circular dependency right now
|
|
191
|
+
this.listenerManager = new ListenerManager(
|
|
158
192
|
this,
|
|
159
193
|
undefined,
|
|
160
|
-
options
|
|
194
|
+
this.options.listenerManager,
|
|
161
195
|
);
|
|
196
|
+
|
|
197
|
+
// todo: pull this into the constructor, depends on listenerManager
|
|
198
|
+
this.transmitterFactory = new TransmitterFactory(this.listenerManager);
|
|
199
|
+
|
|
162
200
|
this.documentModels = documentModels;
|
|
163
201
|
this.storage = storage;
|
|
164
202
|
this.cache = cache;
|
|
@@ -491,7 +529,7 @@ export class BaseDocumentDriveServer
|
|
|
491
529
|
this.getSynchronizationUnitsRevision(driveId, syncUnits)
|
|
492
530
|
.then((syncUnitRevisions) => {
|
|
493
531
|
for (const revision of syncUnitRevisions) {
|
|
494
|
-
this.
|
|
532
|
+
this.listenerManager
|
|
495
533
|
.updateListenerRevision(
|
|
496
534
|
pushListener.listenerId,
|
|
497
535
|
driveId,
|
|
@@ -584,6 +622,8 @@ export class BaseDocumentDriveServer
|
|
|
584
622
|
}
|
|
585
623
|
|
|
586
624
|
private async _initialize() {
|
|
625
|
+
await this.listenerManager.initialize(this.handleListenerError);
|
|
626
|
+
|
|
587
627
|
await this.queueManager.init(this.queueDelegate, (error) => {
|
|
588
628
|
logger.error(`Error initializing queue manager`, error);
|
|
589
629
|
errors.push(error);
|
|
@@ -608,22 +648,6 @@ export class BaseDocumentDriveServer
|
|
|
608
648
|
await this.defaultDrivesManager.initializeDefaultRemoteDrives();
|
|
609
649
|
}
|
|
610
650
|
|
|
611
|
-
// if network connect comes back online
|
|
612
|
-
// then triggers the listeners update
|
|
613
|
-
if (typeof window !== "undefined") {
|
|
614
|
-
window.addEventListener("online", () => {
|
|
615
|
-
this.listenerStateManager
|
|
616
|
-
.triggerUpdate(
|
|
617
|
-
false,
|
|
618
|
-
{ type: "local" },
|
|
619
|
-
this.handleListenerError.bind(this),
|
|
620
|
-
)
|
|
621
|
-
.catch((error) => {
|
|
622
|
-
logger.error("Non handled error updating listeners", error);
|
|
623
|
-
});
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
|
|
627
651
|
return errors.length === 0 ? null : errors;
|
|
628
652
|
}
|
|
629
653
|
|
|
@@ -635,7 +659,28 @@ export class BaseDocumentDriveServer
|
|
|
635
659
|
await this.startSyncRemoteDrive(driveId);
|
|
636
660
|
}
|
|
637
661
|
|
|
638
|
-
|
|
662
|
+
for (const zodListener of drive.state.local.listeners) {
|
|
663
|
+
const transmitter = this.transmitterFactory.instance(
|
|
664
|
+
zodListener.callInfo?.transmitterType ?? "",
|
|
665
|
+
zodListener as any,
|
|
666
|
+
this,
|
|
667
|
+
);
|
|
668
|
+
|
|
669
|
+
await this.listenerManager.setListener(driveId, {
|
|
670
|
+
block: zodListener.block,
|
|
671
|
+
driveId: drive.state.global.id,
|
|
672
|
+
filter: {
|
|
673
|
+
branch: zodListener.filter.branch ?? [],
|
|
674
|
+
documentId: zodListener.filter.documentId ?? [],
|
|
675
|
+
documentType: zodListener.filter.documentType,
|
|
676
|
+
scope: zodListener.filter.scope ?? [],
|
|
677
|
+
},
|
|
678
|
+
listenerId: zodListener.listenerId,
|
|
679
|
+
system: zodListener.system,
|
|
680
|
+
label: zodListener.label ?? "",
|
|
681
|
+
transmitter,
|
|
682
|
+
});
|
|
683
|
+
}
|
|
639
684
|
}
|
|
640
685
|
|
|
641
686
|
public async getSynchronizationUnits(
|
|
@@ -899,8 +944,8 @@ export class BaseDocumentDriveServer
|
|
|
899
944
|
return [...this.documentModels];
|
|
900
945
|
}
|
|
901
946
|
|
|
902
|
-
async addDrive(
|
|
903
|
-
const id =
|
|
947
|
+
async addDrive(input: DriveInput): Promise<DocumentDriveDocument> {
|
|
948
|
+
const id = input.global.id || generateUUID();
|
|
904
949
|
if (!id) {
|
|
905
950
|
throw new Error("Invalid Drive Id");
|
|
906
951
|
}
|
|
@@ -911,13 +956,13 @@ export class BaseDocumentDriveServer
|
|
|
911
956
|
}
|
|
912
957
|
|
|
913
958
|
const document = utils.createDocument({
|
|
914
|
-
state:
|
|
959
|
+
state: input,
|
|
915
960
|
});
|
|
916
961
|
|
|
917
962
|
await this.storage.createDrive(id, document);
|
|
918
963
|
|
|
919
|
-
if (
|
|
920
|
-
await this.cache.deleteDocument("drives-slug",
|
|
964
|
+
if (input.global.slug) {
|
|
965
|
+
await this.cache.deleteDocument("drives-slug", input.global.slug);
|
|
921
966
|
}
|
|
922
967
|
|
|
923
968
|
await this._initializeDrive(id);
|
|
@@ -966,13 +1011,13 @@ export class BaseDocumentDriveServer
|
|
|
966
1011
|
}
|
|
967
1012
|
|
|
968
1013
|
public async registerPullResponderTrigger(
|
|
969
|
-
|
|
1014
|
+
driveId: string,
|
|
970
1015
|
url: string,
|
|
971
1016
|
options: Pick<RemoteDriveOptions, "pullFilter" | "pullInterval">,
|
|
972
1017
|
) {
|
|
973
1018
|
const pullTrigger =
|
|
974
1019
|
await PullResponderTransmitter.createPullResponderTrigger(
|
|
975
|
-
|
|
1020
|
+
driveId,
|
|
976
1021
|
url,
|
|
977
1022
|
options,
|
|
978
1023
|
);
|
|
@@ -980,12 +1025,12 @@ export class BaseDocumentDriveServer
|
|
|
980
1025
|
return pullTrigger;
|
|
981
1026
|
}
|
|
982
1027
|
|
|
983
|
-
async deleteDrive(
|
|
1028
|
+
async deleteDrive(driveId: string) {
|
|
984
1029
|
const result = await Promise.allSettled([
|
|
985
|
-
this.stopSyncRemoteDrive(
|
|
986
|
-
this.
|
|
987
|
-
this.cache.deleteDocument("drives",
|
|
988
|
-
this.storage.deleteDrive(
|
|
1030
|
+
this.stopSyncRemoteDrive(driveId),
|
|
1031
|
+
this.listenerManager.removeDrive(driveId),
|
|
1032
|
+
this.cache.deleteDocument("drives", driveId),
|
|
1033
|
+
this.storage.deleteDrive(driveId),
|
|
989
1034
|
]);
|
|
990
1035
|
|
|
991
1036
|
result.forEach((r) => {
|
|
@@ -999,10 +1044,10 @@ export class BaseDocumentDriveServer
|
|
|
999
1044
|
return this.storage.getDrives();
|
|
1000
1045
|
}
|
|
1001
1046
|
|
|
1002
|
-
async getDrive(
|
|
1047
|
+
async getDrive(driveId: string, options?: GetDocumentOptions) {
|
|
1003
1048
|
let document: DocumentDriveDocument | undefined;
|
|
1004
1049
|
try {
|
|
1005
|
-
const cachedDocument = await this.cache.getDocument("drives",
|
|
1050
|
+
const cachedDocument = await this.cache.getDocument("drives", driveId); // TODO support GetDocumentOptions
|
|
1006
1051
|
if (cachedDocument && isDocumentDrive(cachedDocument)) {
|
|
1007
1052
|
document = cachedDocument;
|
|
1008
1053
|
if (isAtRevision(document, options?.revisions)) {
|
|
@@ -1012,13 +1057,13 @@ export class BaseDocumentDriveServer
|
|
|
1012
1057
|
} catch (e) {
|
|
1013
1058
|
logger.error("Error getting drive from cache", e);
|
|
1014
1059
|
}
|
|
1015
|
-
const driveStorage = document ?? (await this.storage.getDrive(
|
|
1060
|
+
const driveStorage = document ?? (await this.storage.getDrive(driveId));
|
|
1016
1061
|
const result = this._buildDocument(driveStorage, options);
|
|
1017
1062
|
if (!isDocumentDrive(result)) {
|
|
1018
|
-
throw new Error(`Document with id ${
|
|
1063
|
+
throw new Error(`Document with id ${driveId} is not a Document Drive`);
|
|
1019
1064
|
} else {
|
|
1020
1065
|
if (!options?.revisions) {
|
|
1021
|
-
this.cache.setDocument("drives",
|
|
1066
|
+
this.cache.setDocument("drives", driveId, result).catch(logger.error);
|
|
1022
1067
|
}
|
|
1023
1068
|
return result;
|
|
1024
1069
|
}
|
|
@@ -1044,10 +1089,14 @@ export class BaseDocumentDriveServer
|
|
|
1044
1089
|
}
|
|
1045
1090
|
}
|
|
1046
1091
|
|
|
1047
|
-
async getDocument(
|
|
1092
|
+
async getDocument(
|
|
1093
|
+
driveId: string,
|
|
1094
|
+
documentId: string,
|
|
1095
|
+
options?: GetDocumentOptions,
|
|
1096
|
+
) {
|
|
1048
1097
|
let cachedDocument: Document | undefined;
|
|
1049
1098
|
try {
|
|
1050
|
-
cachedDocument = await this.cache.getDocument(
|
|
1099
|
+
cachedDocument = await this.cache.getDocument(driveId, documentId); // TODO support GetDocumentOptions
|
|
1051
1100
|
if (cachedDocument && isAtRevision(cachedDocument, options?.revisions)) {
|
|
1052
1101
|
return cachedDocument;
|
|
1053
1102
|
}
|
|
@@ -1055,17 +1104,17 @@ export class BaseDocumentDriveServer
|
|
|
1055
1104
|
logger.error("Error getting document from cache", e);
|
|
1056
1105
|
}
|
|
1057
1106
|
const documentStorage =
|
|
1058
|
-
cachedDocument ?? (await this.storage.getDocument(
|
|
1107
|
+
cachedDocument ?? (await this.storage.getDocument(driveId, documentId));
|
|
1059
1108
|
const document = this._buildDocument(documentStorage, options);
|
|
1060
1109
|
|
|
1061
1110
|
if (!options?.revisions) {
|
|
1062
|
-
this.cache.setDocument(
|
|
1111
|
+
this.cache.setDocument(driveId, documentId, document).catch(logger.error);
|
|
1063
1112
|
}
|
|
1064
1113
|
return document;
|
|
1065
1114
|
}
|
|
1066
1115
|
|
|
1067
|
-
getDocuments(
|
|
1068
|
-
return this.storage.getDocuments(
|
|
1116
|
+
getDocuments(driveId: string) {
|
|
1117
|
+
return this.storage.getDocuments(driveId);
|
|
1069
1118
|
}
|
|
1070
1119
|
|
|
1071
1120
|
protected async createDocument(driveId: string, input: CreateDocumentInput) {
|
|
@@ -1102,7 +1151,7 @@ export class BaseDocumentDriveServer
|
|
|
1102
1151
|
for (const syncUnit of input.synchronizationUnits) {
|
|
1103
1152
|
this.initSyncStatus(syncUnit.syncId, {
|
|
1104
1153
|
pull: this.triggerMap.get(driveId) ? "INITIAL_SYNC" : undefined,
|
|
1105
|
-
push: this.
|
|
1154
|
+
push: this.listenerManager.driveHasListeners(driveId)
|
|
1106
1155
|
? "SUCCESS"
|
|
1107
1156
|
: undefined,
|
|
1108
1157
|
});
|
|
@@ -1131,24 +1180,26 @@ export class BaseDocumentDriveServer
|
|
|
1131
1180
|
return document;
|
|
1132
1181
|
}
|
|
1133
1182
|
|
|
1134
|
-
async deleteDocument(driveId: string,
|
|
1183
|
+
async deleteDocument(driveId: string, documentId: string) {
|
|
1135
1184
|
try {
|
|
1136
|
-
const syncUnits = await this.getSynchronizationUnitsIds(driveId, [
|
|
1185
|
+
const syncUnits = await this.getSynchronizationUnitsIds(driveId, [
|
|
1186
|
+
documentId,
|
|
1187
|
+
]);
|
|
1137
1188
|
|
|
1138
1189
|
// remove document sync units status when a document is deleted
|
|
1139
1190
|
for (const syncUnit of syncUnits) {
|
|
1140
1191
|
this.updateSyncUnitStatus(syncUnit.syncId, null);
|
|
1141
1192
|
}
|
|
1142
|
-
await this.
|
|
1193
|
+
await this.listenerManager.removeSyncUnits(driveId, syncUnits);
|
|
1143
1194
|
} catch (error) {
|
|
1144
1195
|
logger.warn("Error deleting document", error);
|
|
1145
1196
|
}
|
|
1146
|
-
await this.cache.deleteDocument(driveId,
|
|
1147
|
-
return this.storage.deleteDocument(driveId,
|
|
1197
|
+
await this.cache.deleteDocument(driveId, documentId);
|
|
1198
|
+
return this.storage.deleteDocument(driveId, documentId);
|
|
1148
1199
|
}
|
|
1149
1200
|
|
|
1150
1201
|
async _processOperations<T extends Document, A extends Action>(
|
|
1151
|
-
|
|
1202
|
+
driveId: string,
|
|
1152
1203
|
documentId: string | undefined,
|
|
1153
1204
|
documentStorage: DocumentStorage<T>,
|
|
1154
1205
|
operations: Operation<A | BaseAction>[],
|
|
@@ -1158,7 +1209,7 @@ export class BaseDocumentDriveServer
|
|
|
1158
1209
|
|
|
1159
1210
|
const documentStorageWithState = await this._addDocumentResultingStage(
|
|
1160
1211
|
documentStorage,
|
|
1161
|
-
|
|
1212
|
+
driveId,
|
|
1162
1213
|
documentId,
|
|
1163
1214
|
);
|
|
1164
1215
|
|
|
@@ -1215,7 +1266,7 @@ export class BaseDocumentDriveServer
|
|
|
1215
1266
|
const taskQueueMethod = this.options.taskQueueMethod;
|
|
1216
1267
|
const task = () =>
|
|
1217
1268
|
this._performOperation(
|
|
1218
|
-
|
|
1269
|
+
driveId,
|
|
1219
1270
|
documentId,
|
|
1220
1271
|
document,
|
|
1221
1272
|
nextOperation,
|
|
@@ -1256,7 +1307,7 @@ export class BaseDocumentDriveServer
|
|
|
1256
1307
|
|
|
1257
1308
|
private async _addDocumentResultingStage<T extends Document>(
|
|
1258
1309
|
document: DocumentStorage<T>,
|
|
1259
|
-
|
|
1310
|
+
driveId: string,
|
|
1260
1311
|
documentId?: string,
|
|
1261
1312
|
options?: GetDocumentOptions,
|
|
1262
1313
|
): Promise<DocumentStorage<T>> {
|
|
@@ -1278,14 +1329,14 @@ export class BaseDocumentDriveServer
|
|
|
1278
1329
|
if (lastRemainingOperation && !lastRemainingOperation.resultingState) {
|
|
1279
1330
|
lastRemainingOperation.resultingState = await (documentId
|
|
1280
1331
|
? this.storage.getOperationResultingState?.(
|
|
1281
|
-
|
|
1332
|
+
driveId,
|
|
1282
1333
|
documentId,
|
|
1283
1334
|
lastRemainingOperation.index,
|
|
1284
1335
|
lastRemainingOperation.scope,
|
|
1285
1336
|
"main",
|
|
1286
1337
|
)
|
|
1287
1338
|
: this.storage.getDriveOperationResultingState?.(
|
|
1288
|
-
|
|
1339
|
+
driveId,
|
|
1289
1340
|
lastRemainingOperation.index,
|
|
1290
1341
|
lastRemainingOperation.scope,
|
|
1291
1342
|
"main",
|
|
@@ -1341,8 +1392,8 @@ export class BaseDocumentDriveServer
|
|
|
1341
1392
|
}
|
|
1342
1393
|
|
|
1343
1394
|
private async _performOperation<T extends Document>(
|
|
1344
|
-
|
|
1345
|
-
|
|
1395
|
+
driveId: string,
|
|
1396
|
+
documentId: string | undefined,
|
|
1346
1397
|
document: T,
|
|
1347
1398
|
operation: Operation,
|
|
1348
1399
|
skipHashValidation = false,
|
|
@@ -1366,16 +1417,16 @@ export class BaseDocumentDriveServer
|
|
|
1366
1417
|
// if the latest operation doesn't have a resulting state then tries
|
|
1367
1418
|
// to retrieve it from the db to avoid rerunning all the operations
|
|
1368
1419
|
if (lastRemainingOperation && !lastRemainingOperation.resultingState) {
|
|
1369
|
-
lastRemainingOperation.resultingState = await (
|
|
1420
|
+
lastRemainingOperation.resultingState = await (documentId
|
|
1370
1421
|
? this.storage.getOperationResultingState?.(
|
|
1371
|
-
|
|
1372
|
-
|
|
1422
|
+
driveId,
|
|
1423
|
+
documentId,
|
|
1373
1424
|
lastRemainingOperation.index,
|
|
1374
1425
|
lastRemainingOperation.scope,
|
|
1375
1426
|
"main",
|
|
1376
1427
|
)
|
|
1377
1428
|
: this.storage.getDriveOperationResultingState?.(
|
|
1378
|
-
|
|
1429
|
+
driveId,
|
|
1379
1430
|
lastRemainingOperation.index,
|
|
1380
1431
|
lastRemainingOperation.scope,
|
|
1381
1432
|
"main",
|
|
@@ -1390,20 +1441,21 @@ export class BaseDocumentDriveServer
|
|
|
1390
1441
|
let handler: (() => Promise<unknown>) | undefined = undefined;
|
|
1391
1442
|
switch (signal.type) {
|
|
1392
1443
|
case "CREATE_CHILD_DOCUMENT":
|
|
1393
|
-
handler = () => this.createDocument(
|
|
1444
|
+
handler = () => this.createDocument(driveId, signal.input);
|
|
1394
1445
|
break;
|
|
1395
1446
|
case "DELETE_CHILD_DOCUMENT":
|
|
1396
|
-
handler = () => this.deleteDocument(
|
|
1447
|
+
handler = () => this.deleteDocument(driveId, signal.input.id);
|
|
1397
1448
|
break;
|
|
1398
1449
|
case "COPY_CHILD_DOCUMENT":
|
|
1399
1450
|
handler = () =>
|
|
1400
|
-
this.getDocument(
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1451
|
+
this.getDocument(driveId, signal.input.id).then(
|
|
1452
|
+
(documentToCopy) =>
|
|
1453
|
+
this.createDocument(driveId, {
|
|
1454
|
+
id: signal.input.newId,
|
|
1455
|
+
documentType: documentToCopy.documentType,
|
|
1456
|
+
document: documentToCopy,
|
|
1457
|
+
synchronizationUnits: signal.input.synchronizationUnits,
|
|
1458
|
+
}),
|
|
1407
1459
|
);
|
|
1408
1460
|
break;
|
|
1409
1461
|
}
|
|
@@ -1449,50 +1501,53 @@ export class BaseDocumentDriveServer
|
|
|
1449
1501
|
}
|
|
1450
1502
|
|
|
1451
1503
|
addOperation(
|
|
1452
|
-
|
|
1453
|
-
|
|
1504
|
+
driveId: string,
|
|
1505
|
+
documentId: string,
|
|
1454
1506
|
operation: Operation,
|
|
1455
1507
|
options?: AddOperationOptions,
|
|
1456
1508
|
): Promise<IOperationResult> {
|
|
1457
|
-
return this.addOperations(
|
|
1509
|
+
return this.addOperations(driveId, documentId, [operation], options);
|
|
1458
1510
|
}
|
|
1459
1511
|
|
|
1460
1512
|
private async _addOperations(
|
|
1461
|
-
|
|
1462
|
-
|
|
1513
|
+
driveId: string,
|
|
1514
|
+
documentId: string,
|
|
1463
1515
|
callback: (document: DocumentStorage) => Promise<{
|
|
1464
1516
|
operations: Operation[];
|
|
1465
1517
|
header: DocumentHeader;
|
|
1466
1518
|
}>,
|
|
1467
1519
|
) {
|
|
1468
1520
|
if (!this.storage.addDocumentOperationsWithTransaction) {
|
|
1469
|
-
const documentStorage = await this.storage.getDocument(
|
|
1521
|
+
const documentStorage = await this.storage.getDocument(
|
|
1522
|
+
driveId,
|
|
1523
|
+
documentId,
|
|
1524
|
+
);
|
|
1470
1525
|
const result = await callback(documentStorage);
|
|
1471
1526
|
// saves the applied operations to storage
|
|
1472
1527
|
if (result.operations.length > 0) {
|
|
1473
1528
|
await this.storage.addDocumentOperations(
|
|
1474
|
-
|
|
1475
|
-
|
|
1529
|
+
driveId,
|
|
1530
|
+
documentId,
|
|
1476
1531
|
result.operations,
|
|
1477
1532
|
result.header,
|
|
1478
1533
|
);
|
|
1479
1534
|
}
|
|
1480
1535
|
} else {
|
|
1481
1536
|
await this.storage.addDocumentOperationsWithTransaction(
|
|
1482
|
-
|
|
1483
|
-
|
|
1537
|
+
driveId,
|
|
1538
|
+
documentId,
|
|
1484
1539
|
callback,
|
|
1485
1540
|
);
|
|
1486
1541
|
}
|
|
1487
1542
|
}
|
|
1488
1543
|
|
|
1489
1544
|
queueOperation(
|
|
1490
|
-
|
|
1491
|
-
|
|
1545
|
+
driveId: string,
|
|
1546
|
+
documentId: string,
|
|
1492
1547
|
operation: Operation,
|
|
1493
1548
|
options?: AddOperationOptions,
|
|
1494
1549
|
): Promise<IOperationResult> {
|
|
1495
|
-
return this.queueOperations(
|
|
1550
|
+
return this.queueOperations(driveId, documentId, [operation], options);
|
|
1496
1551
|
}
|
|
1497
1552
|
|
|
1498
1553
|
private async resultIfExistingOperations(
|
|
@@ -1534,20 +1589,24 @@ export class BaseDocumentDriveServer
|
|
|
1534
1589
|
}
|
|
1535
1590
|
|
|
1536
1591
|
async queueOperations(
|
|
1537
|
-
|
|
1538
|
-
|
|
1592
|
+
driveId: string,
|
|
1593
|
+
documentId: string,
|
|
1539
1594
|
operations: Operation[],
|
|
1540
1595
|
options?: AddOperationOptions,
|
|
1541
1596
|
) {
|
|
1542
1597
|
// if operations are already stored then returns cached document
|
|
1543
|
-
const result = await this.resultIfExistingOperations(
|
|
1598
|
+
const result = await this.resultIfExistingOperations(
|
|
1599
|
+
driveId,
|
|
1600
|
+
documentId,
|
|
1601
|
+
operations,
|
|
1602
|
+
);
|
|
1544
1603
|
if (result) {
|
|
1545
1604
|
return result;
|
|
1546
1605
|
}
|
|
1547
1606
|
try {
|
|
1548
1607
|
const jobId = await this.queueManager.addJob({
|
|
1549
|
-
driveId:
|
|
1550
|
-
documentId:
|
|
1608
|
+
driveId: driveId,
|
|
1609
|
+
documentId: documentId,
|
|
1551
1610
|
operations,
|
|
1552
1611
|
options,
|
|
1553
1612
|
});
|
|
@@ -1581,24 +1640,24 @@ export class BaseDocumentDriveServer
|
|
|
1581
1640
|
}
|
|
1582
1641
|
|
|
1583
1642
|
async queueAction(
|
|
1584
|
-
|
|
1585
|
-
|
|
1643
|
+
driveId: string,
|
|
1644
|
+
documentId: string,
|
|
1586
1645
|
action: Action,
|
|
1587
1646
|
options?: AddOperationOptions,
|
|
1588
1647
|
): Promise<IOperationResult> {
|
|
1589
|
-
return this.queueActions(
|
|
1648
|
+
return this.queueActions(driveId, documentId, [action], options);
|
|
1590
1649
|
}
|
|
1591
1650
|
|
|
1592
1651
|
async queueActions(
|
|
1593
|
-
|
|
1594
|
-
|
|
1652
|
+
driveId: string,
|
|
1653
|
+
documentId: string,
|
|
1595
1654
|
actions: Action[],
|
|
1596
1655
|
options?: AddOperationOptions,
|
|
1597
1656
|
): Promise<IOperationResult> {
|
|
1598
1657
|
try {
|
|
1599
1658
|
const jobId = await this.queueManager.addJob({
|
|
1600
|
-
driveId:
|
|
1601
|
-
documentId:
|
|
1659
|
+
driveId: driveId,
|
|
1660
|
+
documentId: documentId,
|
|
1602
1661
|
actions,
|
|
1603
1662
|
options,
|
|
1604
1663
|
});
|
|
@@ -1632,21 +1691,21 @@ export class BaseDocumentDriveServer
|
|
|
1632
1691
|
}
|
|
1633
1692
|
|
|
1634
1693
|
async queueDriveAction(
|
|
1635
|
-
|
|
1694
|
+
driveId: string,
|
|
1636
1695
|
action: DocumentDriveAction | BaseAction,
|
|
1637
1696
|
options?: AddOperationOptions,
|
|
1638
1697
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1639
|
-
return this.queueDriveActions(
|
|
1698
|
+
return this.queueDriveActions(driveId, [action], options);
|
|
1640
1699
|
}
|
|
1641
1700
|
|
|
1642
1701
|
async queueDriveActions(
|
|
1643
|
-
|
|
1702
|
+
driveId: string,
|
|
1644
1703
|
actions: (DocumentDriveAction | BaseAction)[],
|
|
1645
1704
|
options?: AddOperationOptions,
|
|
1646
1705
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1647
1706
|
try {
|
|
1648
1707
|
const jobId = await this.queueManager.addJob({
|
|
1649
|
-
driveId:
|
|
1708
|
+
driveId: driveId,
|
|
1650
1709
|
actions,
|
|
1651
1710
|
options,
|
|
1652
1711
|
});
|
|
@@ -1681,13 +1740,17 @@ export class BaseDocumentDriveServer
|
|
|
1681
1740
|
}
|
|
1682
1741
|
|
|
1683
1742
|
async addOperations(
|
|
1684
|
-
|
|
1685
|
-
|
|
1743
|
+
driveId: string,
|
|
1744
|
+
documentId: string,
|
|
1686
1745
|
operations: Operation[],
|
|
1687
1746
|
options?: AddOperationOptions,
|
|
1688
1747
|
) {
|
|
1689
1748
|
// if operations are already stored then returns the result
|
|
1690
|
-
const result = await this.resultIfExistingOperations(
|
|
1749
|
+
const result = await this.resultIfExistingOperations(
|
|
1750
|
+
driveId,
|
|
1751
|
+
documentId,
|
|
1752
|
+
operations,
|
|
1753
|
+
);
|
|
1691
1754
|
if (result) {
|
|
1692
1755
|
return result;
|
|
1693
1756
|
}
|
|
@@ -1697,33 +1760,39 @@ export class BaseDocumentDriveServer
|
|
|
1697
1760
|
let error: Error | undefined;
|
|
1698
1761
|
|
|
1699
1762
|
try {
|
|
1700
|
-
await this._addOperations(
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1763
|
+
await this._addOperations(
|
|
1764
|
+
driveId,
|
|
1765
|
+
documentId,
|
|
1766
|
+
async (documentStorage) => {
|
|
1767
|
+
const result = await this._processOperations(
|
|
1768
|
+
driveId,
|
|
1769
|
+
documentId,
|
|
1770
|
+
documentStorage,
|
|
1771
|
+
operations,
|
|
1772
|
+
);
|
|
1707
1773
|
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1774
|
+
if (!result.document) {
|
|
1775
|
+
logger.error("Invalid document");
|
|
1776
|
+
throw result.error ?? new Error("Invalid document");
|
|
1777
|
+
}
|
|
1712
1778
|
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1779
|
+
document = result.document;
|
|
1780
|
+
error = result.error;
|
|
1781
|
+
signals.push(...result.signals);
|
|
1782
|
+
operationsApplied.push(...result.operationsApplied);
|
|
1717
1783
|
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1784
|
+
return {
|
|
1785
|
+
operations: result.operationsApplied,
|
|
1786
|
+
header: result.document,
|
|
1787
|
+
newState: document.state,
|
|
1788
|
+
};
|
|
1789
|
+
},
|
|
1790
|
+
);
|
|
1724
1791
|
|
|
1725
1792
|
if (document) {
|
|
1726
|
-
this.cache
|
|
1793
|
+
this.cache
|
|
1794
|
+
.setDocument(driveId, documentId, document)
|
|
1795
|
+
.catch(logger.error);
|
|
1727
1796
|
}
|
|
1728
1797
|
|
|
1729
1798
|
// gets all the different scopes and branches combinations from the operations
|
|
@@ -1738,8 +1807,8 @@ export class BaseDocumentDriveServer
|
|
|
1738
1807
|
);
|
|
1739
1808
|
|
|
1740
1809
|
const syncUnits = await this.getSynchronizationUnits(
|
|
1741
|
-
|
|
1742
|
-
[
|
|
1810
|
+
driveId,
|
|
1811
|
+
[documentId],
|
|
1743
1812
|
scopes,
|
|
1744
1813
|
branches,
|
|
1745
1814
|
);
|
|
@@ -1767,13 +1836,13 @@ export class BaseDocumentDriveServer
|
|
|
1767
1836
|
|
|
1768
1837
|
const operationSource = this.getOperationSource(source);
|
|
1769
1838
|
|
|
1770
|
-
this.
|
|
1839
|
+
this.listenerManager
|
|
1771
1840
|
.updateSynchronizationRevisions(
|
|
1772
|
-
|
|
1841
|
+
driveId,
|
|
1773
1842
|
syncUnits,
|
|
1774
1843
|
source,
|
|
1775
1844
|
() => {
|
|
1776
|
-
this.updateSyncUnitStatus(
|
|
1845
|
+
this.updateSyncUnitStatus(driveId, {
|
|
1777
1846
|
[operationSource]: "SYNCING",
|
|
1778
1847
|
});
|
|
1779
1848
|
|
|
@@ -1788,7 +1857,7 @@ export class BaseDocumentDriveServer
|
|
|
1788
1857
|
)
|
|
1789
1858
|
.then((updates) => {
|
|
1790
1859
|
if (updates.length) {
|
|
1791
|
-
this.updateSyncUnitStatus(
|
|
1860
|
+
this.updateSyncUnitStatus(driveId, {
|
|
1792
1861
|
[operationSource]: "SUCCESS",
|
|
1793
1862
|
});
|
|
1794
1863
|
}
|
|
@@ -1802,7 +1871,7 @@ export class BaseDocumentDriveServer
|
|
|
1802
1871
|
.catch((error) => {
|
|
1803
1872
|
logger.error("Non handled error updating sync revision", error);
|
|
1804
1873
|
this.updateSyncUnitStatus(
|
|
1805
|
-
|
|
1874
|
+
driveId,
|
|
1806
1875
|
{
|
|
1807
1876
|
[operationSource]: "ERROR",
|
|
1808
1877
|
},
|
|
@@ -1854,11 +1923,11 @@ export class BaseDocumentDriveServer
|
|
|
1854
1923
|
}
|
|
1855
1924
|
|
|
1856
1925
|
addDriveOperation(
|
|
1857
|
-
|
|
1926
|
+
driveId: string,
|
|
1858
1927
|
operation: Operation<DocumentDriveAction | BaseAction>,
|
|
1859
1928
|
options?: AddOperationOptions,
|
|
1860
1929
|
) {
|
|
1861
|
-
return this.addDriveOperations(
|
|
1930
|
+
return this.addDriveOperations(driveId, [operation], options);
|
|
1862
1931
|
}
|
|
1863
1932
|
|
|
1864
1933
|
async clearStorage() {
|
|
@@ -1870,35 +1939,35 @@ export class BaseDocumentDriveServer
|
|
|
1870
1939
|
}
|
|
1871
1940
|
|
|
1872
1941
|
private async _addDriveOperations(
|
|
1873
|
-
|
|
1942
|
+
driveId: string,
|
|
1874
1943
|
callback: (document: DocumentDriveStorage) => Promise<{
|
|
1875
1944
|
operations: Operation<DocumentDriveAction | BaseAction>[];
|
|
1876
1945
|
header: DocumentHeader;
|
|
1877
1946
|
}>,
|
|
1878
1947
|
) {
|
|
1879
1948
|
if (!this.storage.addDriveOperationsWithTransaction) {
|
|
1880
|
-
const documentStorage = await this.storage.getDrive(
|
|
1949
|
+
const documentStorage = await this.storage.getDrive(driveId);
|
|
1881
1950
|
const result = await callback(documentStorage);
|
|
1882
1951
|
// saves the applied operations to storage
|
|
1883
1952
|
if (result.operations.length > 0) {
|
|
1884
1953
|
await this.storage.addDriveOperations(
|
|
1885
|
-
|
|
1954
|
+
driveId,
|
|
1886
1955
|
result.operations,
|
|
1887
1956
|
result.header,
|
|
1888
1957
|
);
|
|
1889
1958
|
}
|
|
1890
1959
|
return result;
|
|
1891
1960
|
} else {
|
|
1892
|
-
return this.storage.addDriveOperationsWithTransaction(
|
|
1961
|
+
return this.storage.addDriveOperationsWithTransaction(driveId, callback);
|
|
1893
1962
|
}
|
|
1894
1963
|
}
|
|
1895
1964
|
|
|
1896
1965
|
queueDriveOperation(
|
|
1897
|
-
|
|
1966
|
+
driveId: string,
|
|
1898
1967
|
operation: Operation<DocumentDriveAction | BaseAction>,
|
|
1899
1968
|
options?: AddOperationOptions,
|
|
1900
1969
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1901
|
-
return this.queueDriveOperations(
|
|
1970
|
+
return this.queueDriveOperations(driveId, [operation], options);
|
|
1902
1971
|
}
|
|
1903
1972
|
|
|
1904
1973
|
private async resultIfExistingDriveOperations(
|
|
@@ -1935,13 +2004,13 @@ export class BaseDocumentDriveServer
|
|
|
1935
2004
|
}
|
|
1936
2005
|
|
|
1937
2006
|
async queueDriveOperations(
|
|
1938
|
-
|
|
2007
|
+
driveId: string,
|
|
1939
2008
|
operations: Operation<DocumentDriveAction | BaseAction>[],
|
|
1940
2009
|
options?: AddOperationOptions,
|
|
1941
2010
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
1942
2011
|
// if operations are already stored then returns cached document
|
|
1943
2012
|
const result = await this.resultIfExistingDriveOperations(
|
|
1944
|
-
|
|
2013
|
+
driveId,
|
|
1945
2014
|
operations,
|
|
1946
2015
|
);
|
|
1947
2016
|
if (result) {
|
|
@@ -1949,7 +2018,7 @@ export class BaseDocumentDriveServer
|
|
|
1949
2018
|
}
|
|
1950
2019
|
try {
|
|
1951
2020
|
const jobId = await this.queueManager.addJob({
|
|
1952
|
-
driveId:
|
|
2021
|
+
driveId: driveId,
|
|
1953
2022
|
operations,
|
|
1954
2023
|
options,
|
|
1955
2024
|
});
|
|
@@ -1984,7 +2053,7 @@ export class BaseDocumentDriveServer
|
|
|
1984
2053
|
}
|
|
1985
2054
|
|
|
1986
2055
|
async addDriveOperations(
|
|
1987
|
-
|
|
2056
|
+
driveId: string,
|
|
1988
2057
|
operations: Operation<DocumentDriveAction | BaseAction>[],
|
|
1989
2058
|
options?: AddOperationOptions,
|
|
1990
2059
|
) {
|
|
@@ -1995,7 +2064,7 @@ export class BaseDocumentDriveServer
|
|
|
1995
2064
|
|
|
1996
2065
|
// if operations are already stored then returns cached drive
|
|
1997
2066
|
const result = await this.resultIfExistingDriveOperations(
|
|
1998
|
-
|
|
2067
|
+
driveId,
|
|
1999
2068
|
operations,
|
|
2000
2069
|
);
|
|
2001
2070
|
if (result) {
|
|
@@ -2003,11 +2072,11 @@ export class BaseDocumentDriveServer
|
|
|
2003
2072
|
}
|
|
2004
2073
|
|
|
2005
2074
|
try {
|
|
2006
|
-
await this._addDriveOperations(
|
|
2075
|
+
await this._addDriveOperations(driveId, async (documentStorage) => {
|
|
2007
2076
|
const result = await this._processOperations<
|
|
2008
2077
|
DocumentDriveDocument,
|
|
2009
2078
|
DocumentDriveAction
|
|
2010
|
-
>(
|
|
2079
|
+
>(driveId, undefined, documentStorage, operations.slice());
|
|
2011
2080
|
document = result.document;
|
|
2012
2081
|
operationsApplied.push(...result.operationsApplied);
|
|
2013
2082
|
signals.push(...result.signals);
|
|
@@ -2023,16 +2092,46 @@ export class BaseDocumentDriveServer
|
|
|
2023
2092
|
throw error ?? new Error("Invalid Document Drive document");
|
|
2024
2093
|
}
|
|
2025
2094
|
|
|
2026
|
-
this.cache.setDocument("drives",
|
|
2095
|
+
this.cache.setDocument("drives", driveId, document).catch(logger.error);
|
|
2027
2096
|
|
|
2028
2097
|
for (const operation of operationsApplied) {
|
|
2029
2098
|
switch (operation.type) {
|
|
2030
2099
|
case "ADD_LISTENER": {
|
|
2031
|
-
|
|
2100
|
+
const zodListener = operation.input.listener;
|
|
2101
|
+
|
|
2102
|
+
// create the transmitter
|
|
2103
|
+
const transmitter = this.transmitterFactory.instance(
|
|
2104
|
+
zodListener.callInfo?.transmitterType ?? "",
|
|
2105
|
+
zodListener as any,
|
|
2106
|
+
this,
|
|
2107
|
+
);
|
|
2108
|
+
|
|
2109
|
+
// create the listener
|
|
2110
|
+
const listener = {
|
|
2111
|
+
...zodListener,
|
|
2112
|
+
driveId: driveId,
|
|
2113
|
+
label: zodListener.label ?? "",
|
|
2114
|
+
system: zodListener.system ?? false,
|
|
2115
|
+
filter: {
|
|
2116
|
+
branch: zodListener.filter.branch ?? [],
|
|
2117
|
+
documentId: zodListener.filter.documentId ?? [],
|
|
2118
|
+
documentType: zodListener.filter.documentType ?? [],
|
|
2119
|
+
scope: zodListener.filter.scope ?? [],
|
|
2120
|
+
},
|
|
2121
|
+
callInfo: {
|
|
2122
|
+
data: zodListener.callInfo?.data ?? "",
|
|
2123
|
+
name: zodListener.callInfo?.name ?? "PullResponder",
|
|
2124
|
+
transmitterType:
|
|
2125
|
+
zodListener.callInfo?.transmitterType ?? "PullResponder",
|
|
2126
|
+
},
|
|
2127
|
+
transmitter,
|
|
2128
|
+
};
|
|
2129
|
+
|
|
2130
|
+
await this.addListener(driveId, listener);
|
|
2032
2131
|
break;
|
|
2033
2132
|
}
|
|
2034
2133
|
case "REMOVE_LISTENER": {
|
|
2035
|
-
await this.removeListener(
|
|
2134
|
+
await this.removeListener(driveId, operation);
|
|
2036
2135
|
break;
|
|
2037
2136
|
}
|
|
2038
2137
|
}
|
|
@@ -2066,13 +2165,13 @@ export class BaseDocumentDriveServer
|
|
|
2066
2165
|
|
|
2067
2166
|
const operationSource = this.getOperationSource(source);
|
|
2068
2167
|
|
|
2069
|
-
this.
|
|
2168
|
+
this.listenerManager
|
|
2070
2169
|
.updateSynchronizationRevisions(
|
|
2071
|
-
|
|
2170
|
+
driveId,
|
|
2072
2171
|
[
|
|
2073
2172
|
{
|
|
2074
2173
|
syncId: "0",
|
|
2075
|
-
driveId:
|
|
2174
|
+
driveId: driveId,
|
|
2076
2175
|
documentId: "",
|
|
2077
2176
|
scope: "global",
|
|
2078
2177
|
branch: "main",
|
|
@@ -2083,7 +2182,7 @@ export class BaseDocumentDriveServer
|
|
|
2083
2182
|
],
|
|
2084
2183
|
source,
|
|
2085
2184
|
() => {
|
|
2086
|
-
this.updateSyncUnitStatus(
|
|
2185
|
+
this.updateSyncUnitStatus(driveId, {
|
|
2087
2186
|
[operationSource]: "SYNCING",
|
|
2088
2187
|
});
|
|
2089
2188
|
},
|
|
@@ -2092,7 +2191,7 @@ export class BaseDocumentDriveServer
|
|
|
2092
2191
|
)
|
|
2093
2192
|
.then((updates) => {
|
|
2094
2193
|
if (updates.length) {
|
|
2095
|
-
this.updateSyncUnitStatus(
|
|
2194
|
+
this.updateSyncUnitStatus(driveId, {
|
|
2096
2195
|
[operationSource]: "SUCCESS",
|
|
2097
2196
|
});
|
|
2098
2197
|
}
|
|
@@ -2100,7 +2199,7 @@ export class BaseDocumentDriveServer
|
|
|
2100
2199
|
.catch((error) => {
|
|
2101
2200
|
logger.error("Non handled error updating sync revision", error);
|
|
2102
2201
|
this.updateSyncUnitStatus(
|
|
2103
|
-
|
|
2202
|
+
driveId,
|
|
2104
2203
|
{ [operationSource]: "ERROR" },
|
|
2105
2204
|
error as Error,
|
|
2106
2205
|
);
|
|
@@ -2147,14 +2246,14 @@ export class BaseDocumentDriveServer
|
|
|
2147
2246
|
}
|
|
2148
2247
|
|
|
2149
2248
|
private _buildOperations<T extends Action>(
|
|
2150
|
-
|
|
2249
|
+
documentId: Document,
|
|
2151
2250
|
actions: (T | BaseAction)[],
|
|
2152
2251
|
): Operation<T | BaseAction>[] {
|
|
2153
2252
|
const operations: Operation<T | BaseAction>[] = [];
|
|
2154
|
-
const { reducer } = this.getDocumentModel(
|
|
2253
|
+
const { reducer } = this.getDocumentModel(documentId.documentType);
|
|
2155
2254
|
for (const action of actions) {
|
|
2156
|
-
|
|
2157
|
-
const operation =
|
|
2255
|
+
documentId = reducer(documentId, action);
|
|
2256
|
+
const operation = documentId.operations[action.scope].slice().pop();
|
|
2158
2257
|
if (!operation) {
|
|
2159
2258
|
throw new Error("Error creating operations");
|
|
2160
2259
|
}
|
|
@@ -2164,44 +2263,73 @@ export class BaseDocumentDriveServer
|
|
|
2164
2263
|
}
|
|
2165
2264
|
|
|
2166
2265
|
async addAction(
|
|
2167
|
-
|
|
2168
|
-
|
|
2266
|
+
driveId: string,
|
|
2267
|
+
documentId: string,
|
|
2169
2268
|
action: Action,
|
|
2170
2269
|
options?: AddOperationOptions,
|
|
2171
2270
|
): Promise<IOperationResult> {
|
|
2172
|
-
return this.addActions(
|
|
2271
|
+
return this.addActions(driveId, documentId, [action], options);
|
|
2173
2272
|
}
|
|
2174
2273
|
|
|
2175
2274
|
async addActions(
|
|
2176
|
-
|
|
2177
|
-
|
|
2275
|
+
driveId: string,
|
|
2276
|
+
documentId: string,
|
|
2178
2277
|
actions: Action[],
|
|
2179
2278
|
options?: AddOperationOptions,
|
|
2180
2279
|
): Promise<IOperationResult> {
|
|
2181
|
-
const document = await this.getDocument(
|
|
2280
|
+
const document = await this.getDocument(driveId, documentId);
|
|
2182
2281
|
const operations = this._buildOperations(document, actions);
|
|
2183
|
-
return this.addOperations(
|
|
2282
|
+
return this.addOperations(driveId, documentId, operations, options);
|
|
2184
2283
|
}
|
|
2185
2284
|
|
|
2186
2285
|
async addDriveAction(
|
|
2187
|
-
|
|
2286
|
+
driveId: string,
|
|
2188
2287
|
action: DocumentDriveAction | BaseAction,
|
|
2189
2288
|
options?: AddOperationOptions,
|
|
2190
2289
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
2191
|
-
return this.addDriveActions(
|
|
2290
|
+
return this.addDriveActions(driveId, [action], options);
|
|
2192
2291
|
}
|
|
2193
2292
|
|
|
2194
2293
|
async addDriveActions(
|
|
2195
|
-
|
|
2294
|
+
driveId: string,
|
|
2196
2295
|
actions: (DocumentDriveAction | BaseAction)[],
|
|
2197
2296
|
options?: AddOperationOptions,
|
|
2198
2297
|
): Promise<IOperationResult<DocumentDriveDocument>> {
|
|
2199
|
-
const document = await this.getDrive(
|
|
2298
|
+
const document = await this.getDrive(driveId);
|
|
2200
2299
|
const operations = this._buildOperations(document, actions);
|
|
2201
|
-
const result = await this.addDriveOperations(
|
|
2300
|
+
const result = await this.addDriveOperations(driveId, operations, options);
|
|
2202
2301
|
return result;
|
|
2203
2302
|
}
|
|
2204
2303
|
|
|
2304
|
+
async detachDrive(driveId: string) {
|
|
2305
|
+
const documentDrive = await this.getDrive(driveId);
|
|
2306
|
+
const listeners = documentDrive.state.local.listeners || [];
|
|
2307
|
+
const triggers = documentDrive.state.local.triggers || [];
|
|
2308
|
+
|
|
2309
|
+
for (const listener of listeners) {
|
|
2310
|
+
await this.addDriveAction(
|
|
2311
|
+
driveId,
|
|
2312
|
+
actions.removeListener({ listenerId: listener.listenerId }),
|
|
2313
|
+
);
|
|
2314
|
+
}
|
|
2315
|
+
|
|
2316
|
+
for (const trigger of triggers) {
|
|
2317
|
+
await this.addDriveAction(
|
|
2318
|
+
driveId,
|
|
2319
|
+
actions.removeTrigger({ triggerId: trigger.id }),
|
|
2320
|
+
);
|
|
2321
|
+
}
|
|
2322
|
+
|
|
2323
|
+
await this.addDriveAction(
|
|
2324
|
+
driveId,
|
|
2325
|
+
actions.setSharingType({ type: "LOCAL" }),
|
|
2326
|
+
);
|
|
2327
|
+
}
|
|
2328
|
+
|
|
2329
|
+
async addListener(driveId: string, listener: Listener) {
|
|
2330
|
+
await this.listenerManager.setListener(driveId, listener);
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2205
2333
|
async addInternalListener(
|
|
2206
2334
|
driveId: string,
|
|
2207
2335
|
receiver: IReceiver,
|
|
@@ -2236,75 +2364,40 @@ export class BaseDocumentDriveServer
|
|
|
2236
2364
|
return transmitter;
|
|
2237
2365
|
}
|
|
2238
2366
|
|
|
2239
|
-
async detachDrive(driveId: string) {
|
|
2240
|
-
const documentDrive = await this.getDrive(driveId);
|
|
2241
|
-
const listeners = documentDrive.state.local.listeners || [];
|
|
2242
|
-
const triggers = documentDrive.state.local.triggers || [];
|
|
2243
|
-
|
|
2244
|
-
for (const listener of listeners) {
|
|
2245
|
-
await this.addDriveAction(
|
|
2246
|
-
driveId,
|
|
2247
|
-
actions.removeListener({ listenerId: listener.listenerId }),
|
|
2248
|
-
);
|
|
2249
|
-
}
|
|
2250
|
-
|
|
2251
|
-
for (const trigger of triggers) {
|
|
2252
|
-
await this.addDriveAction(
|
|
2253
|
-
driveId,
|
|
2254
|
-
actions.removeTrigger({ triggerId: trigger.id }),
|
|
2255
|
-
);
|
|
2256
|
-
}
|
|
2257
|
-
|
|
2258
|
-
await this.addDriveAction(
|
|
2259
|
-
driveId,
|
|
2260
|
-
actions.setSharingType({ type: "LOCAL" }),
|
|
2261
|
-
);
|
|
2262
|
-
}
|
|
2263
|
-
|
|
2264
|
-
private async addListener(
|
|
2265
|
-
driveId: string,
|
|
2266
|
-
operation: Operation<Action<"ADD_LISTENER", AddListenerInput>>,
|
|
2267
|
-
) {
|
|
2268
|
-
const { listener } = operation.input;
|
|
2269
|
-
await this.listenerStateManager.addListener({
|
|
2270
|
-
...listener,
|
|
2271
|
-
driveId,
|
|
2272
|
-
label: listener.label ?? "",
|
|
2273
|
-
system: listener.system ?? false,
|
|
2274
|
-
filter: {
|
|
2275
|
-
branch: listener.filter.branch ?? [],
|
|
2276
|
-
documentId: listener.filter.documentId ?? [],
|
|
2277
|
-
documentType: listener.filter.documentType ?? [],
|
|
2278
|
-
scope: listener.filter.scope ?? [],
|
|
2279
|
-
},
|
|
2280
|
-
callInfo: {
|
|
2281
|
-
data: listener.callInfo?.data ?? "",
|
|
2282
|
-
name: listener.callInfo?.name ?? "PullResponder",
|
|
2283
|
-
transmitterType: listener.callInfo?.transmitterType ?? "PullResponder",
|
|
2284
|
-
},
|
|
2285
|
-
});
|
|
2286
|
-
}
|
|
2287
|
-
|
|
2288
2367
|
private async removeListener(
|
|
2289
2368
|
driveId: string,
|
|
2290
2369
|
operation: Operation<Action<"REMOVE_LISTENER", RemoveListenerInput>>,
|
|
2291
2370
|
) {
|
|
2292
2371
|
const { listenerId } = operation.input;
|
|
2293
|
-
await this.
|
|
2372
|
+
await this.listenerManager.removeListener(driveId, listenerId);
|
|
2294
2373
|
}
|
|
2295
2374
|
|
|
2296
|
-
getTransmitter(
|
|
2375
|
+
async getTransmitter(
|
|
2297
2376
|
driveId: string,
|
|
2298
2377
|
listenerId: string,
|
|
2299
2378
|
): Promise<ITransmitter | undefined> {
|
|
2300
|
-
|
|
2379
|
+
const listener = await this.listenerManager.getListenerState(
|
|
2380
|
+
driveId,
|
|
2381
|
+
listenerId,
|
|
2382
|
+
);
|
|
2383
|
+
return listener?.listener.transmitter;
|
|
2301
2384
|
}
|
|
2302
2385
|
|
|
2303
2386
|
getListener(
|
|
2304
2387
|
driveId: string,
|
|
2305
2388
|
listenerId: string,
|
|
2306
2389
|
): Promise<ListenerState | undefined> {
|
|
2307
|
-
|
|
2390
|
+
let listenerState;
|
|
2391
|
+
try {
|
|
2392
|
+
listenerState = this.listenerManager.getListenerState(
|
|
2393
|
+
driveId,
|
|
2394
|
+
listenerId,
|
|
2395
|
+
);
|
|
2396
|
+
} catch {
|
|
2397
|
+
return Promise.resolve(undefined);
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2400
|
+
return Promise.resolve(listenerState);
|
|
2308
2401
|
}
|
|
2309
2402
|
|
|
2310
2403
|
getSyncStatus(
|