document-drive 1.28.2 → 1.28.3
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/dist/prisma/schema.prisma +19 -19
- package/dist/src/storage/browser.d.ts +4 -3
- package/dist/src/storage/browser.d.ts.map +1 -1
- package/dist/src/storage/browser.js +23 -11
- package/dist/src/storage/filesystem.d.ts +7 -6
- package/dist/src/storage/filesystem.d.ts.map +1 -1
- package/dist/src/storage/filesystem.js +41 -26
- package/dist/src/storage/ipfs.d.ts +38 -0
- package/dist/src/storage/ipfs.d.ts.map +1 -0
- package/dist/src/storage/ipfs.js +274 -0
- package/dist/src/storage/memory.d.ts +5 -1
- package/dist/src/storage/memory.d.ts.map +1 -1
- package/dist/src/storage/memory.js +78 -35
- package/dist/src/storage/prisma/index.d.ts +4 -2
- package/dist/src/storage/prisma/index.d.ts.map +1 -1
- package/dist/src/storage/prisma/index.js +134 -48
- package/dist/src/storage/sequelize.d.ts +1 -32
- package/dist/src/storage/sequelize.d.ts.map +1 -1
- package/dist/src/storage/sequelize.js +491 -349
- package/dist/src/storage/types.d.ts +1 -0
- package/dist/src/storage/types.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -5
|
@@ -1,375 +1,517 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
|
111
|
-
|
|
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
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
-
|
|
235
|
-
|
|
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
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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
|
-
|
|
301
|
-
|
|
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
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
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
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
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
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
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
|
+
*/
|