document-drive 1.28.2 → 1.28.4

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.
@@ -1,375 +1,517 @@
1
- import { DataTypes, Sequelize } from "sequelize";
2
- export class SequelizeStorage {
3
- db;
4
- constructor(options) {
5
- this.db = new Sequelize(options);
1
+ export {};
2
+ /*
3
+ import {
4
+ type DocumentDriveAction,
5
+ type DocumentDriveDocument,
6
+ type DocumentDriveLocalState,
7
+ type DocumentDriveState,
8
+ } from "#drive-document-model/gen/types";
9
+ import { type SynchronizationUnitQuery } from "#server/types";
10
+ import {
11
+ type AttachmentInput,
12
+ type DocumentHeader,
13
+ type ExtendedState,
14
+ type Operation,
15
+ type OperationScope,
16
+ type PHDocument,
17
+ } from "document-model";
18
+ import { DataTypes, type Options, Sequelize } from "sequelize";
19
+ import { type IDocumentStorage, type IDriveStorage } from "./types.js";
20
+
21
+ export class SequelizeStorage implements IDriveStorage, IDocumentStorage {
22
+ private db: Sequelize;
23
+
24
+ constructor(options: Options) {
25
+ this.db = new Sequelize(options);
26
+ }
27
+
28
+ async exists(id: string): Promise<boolean> {
29
+ const Document = this.db.models.document;
30
+ if (!Document) {
31
+ throw new Error("Document model not found");
6
32
  }
7
- syncModels() {
8
- const Drive = this.db.define("drive", {
9
- slug: {
10
- type: DataTypes.STRING,
11
- primaryKey: true,
12
- },
13
- id: DataTypes.STRING,
14
- });
15
- const Document = this.db.define("document", {
16
- id: {
17
- type: DataTypes.STRING,
18
- primaryKey: true,
19
- },
20
- driveId: {
21
- type: DataTypes.STRING,
22
- primaryKey: true,
23
- },
24
- name: DataTypes.STRING,
25
- documentType: DataTypes.STRING,
26
- initialState: DataTypes.JSON,
27
- lastModified: DataTypes.DATE,
28
- revision: DataTypes.JSON,
29
- });
30
- const Operation = this.db.define("operation", {
31
- driveId: {
32
- type: DataTypes.STRING,
33
- primaryKey: true,
34
- unique: "unique_operation",
35
- },
36
- documentId: {
37
- type: DataTypes.STRING,
38
- primaryKey: true,
39
- unique: "unique_operation",
40
- },
41
- hash: DataTypes.STRING,
42
- index: {
43
- type: DataTypes.INTEGER,
44
- primaryKey: true,
45
- unique: "unique_operation",
46
- },
47
- input: DataTypes.JSON,
48
- timestamp: DataTypes.DATE,
49
- type: DataTypes.STRING,
50
- scope: {
51
- type: DataTypes.STRING,
52
- primaryKey: true,
53
- unique: "unique_operation",
54
- },
55
- branch: {
56
- type: DataTypes.STRING,
57
- primaryKey: true,
58
- unique: "unique_operation",
59
- },
60
- skip: {
61
- type: DataTypes.INTEGER,
62
- defaultValue: 0,
63
- },
64
- });
65
- const Attachment = this.db.define("attachment", {
66
- driveId: {
67
- type: DataTypes.STRING,
68
- primaryKey: true,
69
- },
70
- documentId: {
71
- type: DataTypes.STRING,
72
- primaryKey: true,
73
- },
74
- scope: {
75
- type: DataTypes.STRING,
76
- primaryKey: true,
77
- },
78
- branch: {
79
- type: DataTypes.STRING,
80
- primaryKey: true,
81
- },
82
- index: {
83
- type: DataTypes.STRING,
84
- primaryKey: true,
85
- },
86
- hash: {
87
- type: DataTypes.STRING,
88
- primaryKey: true,
89
- },
90
- mimeType: DataTypes.STRING,
91
- fileName: DataTypes.STRING,
92
- extension: DataTypes.STRING,
93
- data: DataTypes.BLOB,
94
- });
95
- Operation.hasMany(Attachment, {
96
- onDelete: "CASCADE",
97
- });
98
- Attachment.belongsTo(Operation);
99
- Document.hasMany(Operation, {
100
- onDelete: "CASCADE",
101
- });
102
- Operation.belongsTo(Document);
103
- return this.db.sync({ force: true });
33
+ const count = await Document.count({
34
+ where: {
35
+ id: id,
36
+ },
37
+ });
38
+
39
+ return count > 0;
40
+ }
41
+
42
+ async create(id: string, drive: DocumentDriveDocument): Promise<void> {
43
+ const Drive = this.db.models.drive;
44
+ if (!Drive) {
45
+ throw new Error("Drive model not found");
104
46
  }
105
- async createDrive(id, drive) {
106
- await this.createDocument("drives", id, drive);
107
- const Drive = this.db.models.drive;
108
- await Drive.upsert({ id, slug: drive.initialState.state.global.slug });
47
+ await Drive.create({ id, slug: drive.initialState.state.global.slug });
48
+ }
49
+
50
+ public syncModels() {
51
+ const Drive = this.db.define("drive", {
52
+ slug: {
53
+ type: DataTypes.STRING,
54
+ primaryKey: true,
55
+ },
56
+ id: DataTypes.STRING,
57
+ });
58
+ const Document = this.db.define("document", {
59
+ id: {
60
+ type: DataTypes.STRING,
61
+ primaryKey: true,
62
+ },
63
+ driveId: {
64
+ type: DataTypes.STRING,
65
+ primaryKey: true,
66
+ },
67
+ name: DataTypes.STRING,
68
+ documentType: DataTypes.STRING,
69
+ initialState: DataTypes.JSON,
70
+ lastModified: DataTypes.DATE,
71
+ revision: DataTypes.JSON,
72
+ });
73
+
74
+ const Operation = this.db.define("operation", {
75
+ driveId: {
76
+ type: DataTypes.STRING,
77
+ primaryKey: true,
78
+ unique: "unique_operation",
79
+ },
80
+ documentId: {
81
+ type: DataTypes.STRING,
82
+ primaryKey: true,
83
+ unique: "unique_operation",
84
+ },
85
+ hash: DataTypes.STRING,
86
+ index: {
87
+ type: DataTypes.INTEGER,
88
+ primaryKey: true,
89
+ unique: "unique_operation",
90
+ },
91
+ input: DataTypes.JSON,
92
+ timestamp: DataTypes.DATE,
93
+ type: DataTypes.STRING,
94
+ scope: {
95
+ type: DataTypes.STRING,
96
+ primaryKey: true,
97
+ unique: "unique_operation",
98
+ },
99
+ branch: {
100
+ type: DataTypes.STRING,
101
+ primaryKey: true,
102
+ unique: "unique_operation",
103
+ },
104
+ skip: {
105
+ type: DataTypes.INTEGER,
106
+ defaultValue: 0,
107
+ },
108
+ });
109
+
110
+ const Attachment = this.db.define("attachment", {
111
+ driveId: {
112
+ type: DataTypes.STRING,
113
+ primaryKey: true,
114
+ },
115
+ documentId: {
116
+ type: DataTypes.STRING,
117
+ primaryKey: true,
118
+ },
119
+ scope: {
120
+ type: DataTypes.STRING,
121
+ primaryKey: true,
122
+ },
123
+ branch: {
124
+ type: DataTypes.STRING,
125
+ primaryKey: true,
126
+ },
127
+ index: {
128
+ type: DataTypes.STRING,
129
+ primaryKey: true,
130
+ },
131
+ hash: {
132
+ type: DataTypes.STRING,
133
+ primaryKey: true,
134
+ },
135
+ mimeType: DataTypes.STRING,
136
+ fileName: DataTypes.STRING,
137
+ extension: DataTypes.STRING,
138
+ data: DataTypes.BLOB,
139
+ });
140
+
141
+ Operation.hasMany(Attachment, {
142
+ onDelete: "CASCADE",
143
+ });
144
+ Attachment.belongsTo(Operation);
145
+ Document.hasMany(Operation, {
146
+ onDelete: "CASCADE",
147
+ });
148
+ Operation.belongsTo(Document);
149
+
150
+ return this.db.sync({ force: true });
151
+ }
152
+
153
+ async createDrive(id: string, drive: DocumentDriveDocument): Promise<void> {
154
+ await this.createDocument("drives", id, drive);
155
+ const Drive = this.db.models.drive;
156
+ await Drive.upsert({ id, slug: drive.initialState.state.global.slug });
157
+ }
158
+ async addDriveOperations(
159
+ id: string,
160
+ operations: Operation<DocumentDriveAction>[],
161
+ header: DocumentHeader,
162
+ ): Promise<void> {
163
+ await this.addDocumentOperations("drives", id, operations, header);
164
+ }
165
+ async createDocument(
166
+ drive: string,
167
+ id: string,
168
+ document: PHDocument,
169
+ ): Promise<void> {
170
+ const Document = this.db.models.document;
171
+
172
+ if (!Document) {
173
+ throw new Error("Document model not found");
109
174
  }
110
- async addDriveOperations(id, operations, header) {
111
- await this.addDocumentOperations("drives", id, operations, header);
175
+
176
+ await Document.create({
177
+ id: id,
178
+ driveId: drive,
179
+ name: document.name,
180
+ documentType: document.documentType,
181
+ initialState: document.initialState,
182
+ lastModified: document.lastModified,
183
+ revision: document.revision,
184
+ });
185
+ }
186
+ async addDocumentOperations(
187
+ drive: string,
188
+ id: string,
189
+ operations: Operation[],
190
+ header: DocumentHeader,
191
+ ): Promise<void> {
192
+ const document = await this.getDocument(drive, id);
193
+ if (!document) {
194
+ throw new Error(`Document with id ${id} not found`);
112
195
  }
113
- async createDocument(drive, id, document) {
114
- const Document = this.db.models.document;
115
- if (!Document) {
116
- throw new Error("Document model not found");
117
- }
118
- await Document.create({
119
- id: id,
120
- driveId: drive,
121
- name: document.name,
122
- documentType: document.documentType,
123
- initialState: document.initialState,
124
- lastModified: document.lastModified,
125
- revision: document.revision,
126
- });
196
+
197
+ const Operation = this.db.models.operation;
198
+ if (!Operation) {
199
+ throw new Error("Operation model not found");
127
200
  }
128
- async addDocumentOperations(drive, id, operations, header) {
129
- const document = await this.getDocument(drive, id);
130
- if (!document) {
131
- throw new Error(`Document with id ${id} not found`);
132
- }
133
- const Operation = this.db.models.operation;
134
- if (!Operation) {
135
- throw new Error("Operation model not found");
136
- }
137
- await Operation.bulkCreate(operations.map((op) => ({
201
+
202
+ await Operation.bulkCreate(
203
+ operations.map((op) => ({
204
+ driveId: drive,
205
+ documentId: id,
206
+ hash: op.hash,
207
+ index: op.index,
208
+ input: op.input,
209
+ timestamp: op.timestamp,
210
+ type: op.type,
211
+ scope: op.scope,
212
+ branch: "main",
213
+ opId: op.id,
214
+ })),
215
+ );
216
+
217
+ const attachments = operations.reduce<AttachmentInput[]>((acc, op) => {
218
+ if (op.attachments?.length) {
219
+ return acc.concat(
220
+ op.attachments.map((attachment) => ({
138
221
  driveId: drive,
139
222
  documentId: id,
140
- hash: op.hash,
141
- index: op.index,
142
- input: op.input,
143
- timestamp: op.timestamp,
144
- type: op.type,
145
223
  scope: op.scope,
146
224
  branch: "main",
147
- opId: op.id,
148
- })));
149
- const attachments = operations.reduce((acc, op) => {
150
- if (op.attachments?.length) {
151
- return acc.concat(op.attachments.map((attachment) => ({
152
- driveId: drive,
153
- documentId: id,
154
- scope: op.scope,
155
- branch: "main",
156
- index: op.index,
157
- mimeType: attachment.mimeType,
158
- fileName: attachment.fileName,
159
- extension: attachment.extension,
160
- data: attachment.data,
161
- hash: attachment.hash,
162
- })));
163
- }
164
- return acc;
165
- }, []);
166
- if (attachments.length) {
167
- const Attachment = this.db.models.attachment;
168
- if (!Attachment) {
169
- throw new Error("Attachment model not found");
170
- }
171
- await Attachment.bulkCreate(attachments);
172
- }
173
- const Document = this.db.models.document;
174
- if (!Document) {
175
- throw new Error("Document model not found");
176
- }
177
- await Document.update({
178
- lastModified: header.lastModified,
179
- revision: header.revision,
180
- }, {
181
- where: {
182
- id: id,
183
- driveId: drive,
184
- },
185
- });
186
- }
187
- async _addDocumentOperationAttachments(driveId, documentId, operation, attachments) {
188
- const Attachment = this.db.models.attachment;
189
- if (!Attachment) {
190
- throw new Error("Attachment model not found");
191
- }
192
- return Attachment.bulkCreate(attachments.map((attachment) => ({
193
- driveId: driveId,
194
- documentId: documentId,
195
- scope: operation.scope,
196
- branch: "main",
197
- index: operation.index,
225
+ index: op.index,
198
226
  mimeType: attachment.mimeType,
199
227
  fileName: attachment.fileName,
200
228
  extension: attachment.extension,
201
229
  data: attachment.data,
202
230
  hash: attachment.hash,
203
- })));
231
+ })),
232
+ );
233
+ }
234
+ return acc;
235
+ }, []);
236
+ if (attachments.length) {
237
+ const Attachment = this.db.models.attachment;
238
+ if (!Attachment) {
239
+ throw new Error("Attachment model not found");
240
+ }
241
+
242
+ await Attachment.bulkCreate(attachments);
204
243
  }
205
- async getDocuments(drive) {
206
- const Document = this.db.models.document;
207
- if (!Document) {
208
- throw new Error("Document model not found");
209
- }
210
- const result = await Document.findAll({
211
- attributes: ["id"],
212
- where: {
213
- driveId: drive,
214
- },
215
- });
216
- const ids = result.map((e) => {
217
- const { id } = e.dataValues;
218
- return id;
219
- });
220
- return ids;
244
+
245
+ const Document = this.db.models.document;
246
+ if (!Document) {
247
+ throw new Error("Document model not found");
221
248
  }
222
- async exists(id) {
223
- const Document = this.db.models.document;
224
- if (!Document) {
225
- throw new Error("Document model not found");
226
- }
227
- const count = await Document.count({
228
- where: {
229
- id: id,
230
- },
231
- });
232
- return count > 0;
249
+
250
+ await Document.update(
251
+ {
252
+ lastModified: header.lastModified,
253
+ revision: header.revision,
254
+ },
255
+ {
256
+ where: {
257
+ id: id,
258
+ driveId: drive,
259
+ },
260
+ },
261
+ );
262
+ }
263
+
264
+ async _addDocumentOperationAttachments(
265
+ driveId: string,
266
+ documentId: string,
267
+ operation: Operation,
268
+ attachments: AttachmentInput[],
269
+ ) {
270
+ const Attachment = this.db.models.attachment;
271
+ if (!Attachment) {
272
+ throw new Error("Attachment model not found");
233
273
  }
234
- async checkDocumentExists(drive, id) {
235
- return this.exists(id);
274
+
275
+ return Attachment.bulkCreate(
276
+ attachments.map((attachment) => ({
277
+ driveId: driveId,
278
+ documentId: documentId,
279
+ scope: operation.scope,
280
+ branch: "main",
281
+ index: operation.index,
282
+ mimeType: attachment.mimeType,
283
+ fileName: attachment.fileName,
284
+ extension: attachment.extension,
285
+ data: attachment.data,
286
+ hash: attachment.hash,
287
+ })),
288
+ );
289
+ }
290
+
291
+ async getDocuments(drive: string) {
292
+ const Document = this.db.models.document;
293
+ if (!Document) {
294
+ throw new Error("Document model not found");
236
295
  }
237
- async getDocument(driveId, id) {
238
- const documentFromDb = this.db.models.document;
239
- if (!documentFromDb) {
240
- throw new Error("Document model not found");
241
- }
242
- const entry = await documentFromDb.findOne({
243
- where: {
244
- id: id,
245
- driveId: driveId,
246
- },
247
- include: [
248
- {
249
- model: this.db.models.operation,
250
- as: "operations",
251
- },
252
- ],
253
- });
254
- if (entry === null) {
255
- throw new Error(`Document with id ${id} not found`);
256
- }
257
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
258
- const document = entry.dataValues;
259
- const operationFromDb = this.db.models.operation;
260
- if (!operationFromDb) {
261
- throw new Error("Operation model not found");
262
- }
263
- const operations = document.operations.map((op) => ({
264
- hash: op.hash,
265
- index: op.index,
266
- timestamp: new Date(op.timestamp).toISOString(),
267
- input: op.input,
268
- type: op.type,
269
- scope: op.scope,
270
- id: op.opId,
271
- skip: op.skip,
272
- // attachments: fileRegistry
273
- }));
274
- const doc = {
275
- created: document.createdAt.toISOString(),
276
- name: document.name ? document.name : "",
277
- documentType: document.documentType,
278
- initialState: document.initialState,
279
- lastModified: document.updatedAt.toISOString(),
280
- operations: {
281
- global: operations.filter((op) => op.scope === "global"),
282
- local: operations.filter((op) => op.scope === "local"),
283
- },
284
- revision: document.revision,
285
- };
286
- return doc;
296
+
297
+ const result = await Document.findAll({
298
+ attributes: ["id"],
299
+ where: {
300
+ driveId: drive,
301
+ },
302
+ });
303
+
304
+ const ids = result.map((e: { dataValues: { id: string } }) => {
305
+ const { id } = e.dataValues;
306
+ return id;
307
+ });
308
+ return ids;
309
+ }
310
+
311
+ async checkDocumentExists(drive: string, id: string): Promise<boolean> {
312
+ return this.exists(id);
313
+ }
314
+
315
+ async getDocument<TDocument extends PHDocument>(
316
+ driveId: string,
317
+ id: string,
318
+ ): Promise<TDocument> {
319
+ const documentFromDb = this.db.models.document;
320
+ if (!documentFromDb) {
321
+ throw new Error("Document model not found");
287
322
  }
288
- async deleteDocument(drive, id) {
289
- const documentFromDb = this.db.models.document;
290
- if (!documentFromDb) {
291
- throw new Error("Document model not found");
292
- }
293
- await documentFromDb.destroy({
294
- where: {
295
- id: id,
296
- driveId: drive,
297
- },
298
- });
323
+
324
+ const entry = await documentFromDb.findOne({
325
+ where: {
326
+ id: id,
327
+ driveId: driveId,
328
+ },
329
+ include: [
330
+ {
331
+ model: this.db.models.operation,
332
+ as: "operations",
333
+ },
334
+ ],
335
+ });
336
+
337
+ if (entry === null) {
338
+ throw new Error(`Document with id ${id} not found`);
299
339
  }
300
- async getDrives() {
301
- return this.getDocuments("drives");
340
+
341
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
342
+ const document: {
343
+ operations: [
344
+ {
345
+ hash: string;
346
+ index: number;
347
+ timestamp: Date;
348
+ input: JSON;
349
+ type: string;
350
+ scope: string;
351
+ opId?: string;
352
+ skip: number;
353
+ },
354
+ ];
355
+ revision: Record<OperationScope, number>;
356
+ createdAt: Date;
357
+ name: string;
358
+ updatedAt: Date;
359
+ documentType: string;
360
+ initialState: ExtendedState<DocumentDriveState, DocumentDriveLocalState>;
361
+ } = entry.dataValues;
362
+ const operationFromDb = this.db.models.operation;
363
+ if (!operationFromDb) {
364
+ throw new Error("Operation model not found");
302
365
  }
303
- async getDrive(id) {
304
- const doc = await this.getDocument("drives", id);
305
- return doc;
366
+
367
+ const operations = document.operations.map((op) => ({
368
+ hash: op.hash,
369
+ index: op.index,
370
+ timestamp: new Date(op.timestamp).toISOString(),
371
+ input: op.input,
372
+ type: op.type,
373
+ scope: op.scope as OperationScope,
374
+ id: op.opId,
375
+ skip: op.skip,
376
+ // attachments: fileRegistry
377
+ })) as Operation[];
378
+
379
+ const doc = {
380
+ created: document.createdAt.toISOString(),
381
+ name: document.name ? document.name : "",
382
+ documentType: document.documentType,
383
+ initialState: document.initialState,
384
+ lastModified: document.updatedAt.toISOString(),
385
+ operations: {
386
+ global: operations.filter((op) => op.scope === "global"),
387
+ local: operations.filter((op) => op.scope === "local"),
388
+ },
389
+ revision: document.revision,
390
+ };
391
+
392
+ return doc as TDocument;
393
+ }
394
+
395
+ async deleteDocument(drive: string, id: string) {
396
+ const documentFromDb = this.db.models.document;
397
+ if (!documentFromDb) {
398
+ throw new Error("Document model not found");
306
399
  }
307
- async getDriveBySlug(slug) {
308
- const driveFromDb = this.db.models.drive;
309
- if (!driveFromDb) {
310
- throw new Error("Drive model not found");
311
- }
312
- const driveEntity = await driveFromDb.findOne({
313
- where: {
314
- slug,
315
- },
316
- });
317
- if (!driveEntity) {
318
- throw new Error(`Drive with slug ${slug} not found`);
319
- }
320
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
321
- return this.getDrive(driveEntity.dataValues.id);
400
+
401
+ await documentFromDb.destroy({
402
+ where: {
403
+ id: id,
404
+ driveId: drive,
405
+ },
406
+ });
407
+ }
408
+
409
+ async getDrives() {
410
+ return this.getDocuments("drives");
411
+ }
412
+
413
+ async getDrive(id: string) {
414
+ const doc = await this.getDocument("drives", id);
415
+ return doc as DocumentDriveDocument;
416
+ }
417
+
418
+ async getDriveBySlug(slug: string) {
419
+ const driveFromDb = this.db.models.drive;
420
+ if (!driveFromDb) {
421
+ throw new Error("Drive model not found");
322
422
  }
323
- async deleteDrive(id) {
324
- await this.deleteDocument("drives", id);
325
- const documentFromDb = this.db.models.document;
326
- if (!documentFromDb) {
327
- throw new Error("Document model not found");
328
- }
329
- await documentFromDb.destroy({
330
- where: {
331
- driveId: id,
332
- },
333
- });
334
- const driveFromDb = this.db.models.drive;
335
- if (driveFromDb) {
336
- await driveFromDb.destroy({
337
- where: {
338
- id: id,
339
- },
340
- });
341
- }
423
+
424
+ const driveEntity = await driveFromDb.findOne({
425
+ where: {
426
+ slug,
427
+ },
428
+ });
429
+
430
+ if (!driveEntity) {
431
+ throw new Error(`Drive with slug ${slug} not found`);
432
+ }
433
+
434
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
435
+ return this.getDrive(driveEntity.dataValues.id);
436
+ }
437
+
438
+ async deleteDrive(id: string) {
439
+ await this.deleteDocument("drives", id);
440
+
441
+ const documentFromDb = this.db.models.document;
442
+ if (!documentFromDb) {
443
+ throw new Error("Document model not found");
342
444
  }
343
- async getSynchronizationUnitsRevision(units) {
344
- const results = await Promise.allSettled(units.map(async (unit) => {
345
- try {
346
- const document = await (unit.documentId
347
- ? this.getDocument(unit.driveId, unit.documentId)
348
- : this.getDrive(unit.driveId));
349
- if (!document) {
350
- return undefined;
351
- }
352
- const operation = document.operations[unit.scope].at(-1);
353
- if (operation) {
354
- return {
355
- driveId: unit.driveId,
356
- documentId: unit.documentId,
357
- scope: unit.scope,
358
- branch: unit.branch,
359
- lastUpdated: operation.timestamp,
360
- revision: operation.index,
361
- };
362
- }
363
- }
364
- catch {
365
- return undefined;
366
- }
367
- }));
368
- return results.reduce((acc, curr) => {
369
- if (curr.status === "fulfilled" && curr.value !== undefined) {
370
- acc.push(curr.value);
371
- }
372
- return acc;
373
- }, []);
445
+
446
+ await documentFromDb.destroy({
447
+ where: {
448
+ driveId: id,
449
+ },
450
+ });
451
+
452
+ const driveFromDb = this.db.models.drive;
453
+ if (driveFromDb) {
454
+ await driveFromDb.destroy({
455
+ where: {
456
+ id: id,
457
+ },
458
+ });
374
459
  }
460
+ }
461
+
462
+ async getSynchronizationUnitsRevision(
463
+ units: SynchronizationUnitQuery[],
464
+ ): Promise<
465
+ {
466
+ driveId: string;
467
+ documentId: string;
468
+ scope: string;
469
+ branch: string;
470
+ lastUpdated: string;
471
+ revision: number;
472
+ }[]
473
+ > {
474
+ const results = await Promise.allSettled(
475
+ units.map(async (unit) => {
476
+ try {
477
+ const document = await (unit.documentId
478
+ ? this.getDocument(unit.driveId, unit.documentId)
479
+ : this.getDrive(unit.driveId));
480
+ if (!document) {
481
+ return undefined;
482
+ }
483
+ const operation =
484
+ document.operations[unit.scope as OperationScope].at(-1);
485
+ if (operation) {
486
+ return {
487
+ driveId: unit.driveId,
488
+ documentId: unit.documentId,
489
+ scope: unit.scope,
490
+ branch: unit.branch,
491
+ lastUpdated: operation.timestamp,
492
+ revision: operation.index,
493
+ };
494
+ }
495
+ } catch {
496
+ return undefined;
497
+ }
498
+ }),
499
+ );
500
+ return results.reduce<
501
+ {
502
+ driveId: string;
503
+ documentId: string;
504
+ scope: string;
505
+ branch: string;
506
+ lastUpdated: string;
507
+ revision: number;
508
+ }[]
509
+ >((acc, curr) => {
510
+ if (curr.status === "fulfilled" && curr.value !== undefined) {
511
+ acc.push(curr.value);
512
+ }
513
+ return acc;
514
+ }, []);
515
+ }
375
516
  }
517
+ */