appwrite-utils-cli 0.0.286 → 0.9.2
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 +162 -96
- package/dist/collections/attributes.d.ts +4 -0
- package/dist/collections/attributes.js +224 -0
- package/dist/collections/indexes.d.ts +4 -0
- package/dist/collections/indexes.js +27 -0
- package/dist/collections/methods.d.ts +16 -0
- package/dist/collections/methods.js +216 -0
- package/dist/databases/methods.d.ts +6 -0
- package/dist/databases/methods.js +33 -0
- package/dist/interactiveCLI.d.ts +19 -0
- package/dist/interactiveCLI.js +555 -0
- package/dist/main.js +224 -62
- package/dist/migrations/afterImportActions.js +37 -40
- package/dist/migrations/appwriteToX.d.ts +26 -25
- package/dist/migrations/appwriteToX.js +42 -6
- package/dist/migrations/attributes.js +21 -20
- package/dist/migrations/backup.d.ts +93 -87
- package/dist/migrations/collections.d.ts +6 -0
- package/dist/migrations/collections.js +149 -20
- package/dist/migrations/converters.d.ts +2 -18
- package/dist/migrations/converters.js +13 -2
- package/dist/migrations/dataLoader.d.ts +276 -161
- package/dist/migrations/dataLoader.js +535 -292
- package/dist/migrations/databases.js +8 -2
- package/dist/migrations/helper.d.ts +3 -0
- package/dist/migrations/helper.js +21 -0
- package/dist/migrations/importController.d.ts +5 -2
- package/dist/migrations/importController.js +125 -88
- package/dist/migrations/importDataActions.d.ts +9 -1
- package/dist/migrations/importDataActions.js +15 -3
- package/dist/migrations/indexes.js +3 -2
- package/dist/migrations/logging.js +20 -8
- package/dist/migrations/migrationHelper.d.ts +9 -4
- package/dist/migrations/migrationHelper.js +6 -5
- package/dist/migrations/openapi.d.ts +1 -1
- package/dist/migrations/openapi.js +33 -18
- package/dist/migrations/queue.js +3 -2
- package/dist/migrations/relationships.d.ts +2 -2
- package/dist/migrations/schemaStrings.js +53 -41
- package/dist/migrations/setupDatabase.d.ts +2 -4
- package/dist/migrations/setupDatabase.js +24 -105
- package/dist/migrations/storage.d.ts +3 -1
- package/dist/migrations/storage.js +110 -16
- package/dist/migrations/transfer.d.ts +30 -0
- package/dist/migrations/transfer.js +337 -0
- package/dist/migrations/users.d.ts +2 -1
- package/dist/migrations/users.js +78 -43
- package/dist/schemas/authUser.d.ts +2 -2
- package/dist/storage/methods.d.ts +15 -0
- package/dist/storage/methods.js +207 -0
- package/dist/storage/schemas.d.ts +687 -0
- package/dist/storage/schemas.js +175 -0
- package/dist/utils/getClientFromConfig.d.ts +4 -0
- package/dist/utils/getClientFromConfig.js +16 -0
- package/dist/utils/helperFunctions.d.ts +11 -1
- package/dist/utils/helperFunctions.js +38 -0
- package/dist/utils/retryFailedPromises.d.ts +2 -0
- package/dist/utils/retryFailedPromises.js +21 -0
- package/dist/utils/schemaStrings.d.ts +13 -0
- package/dist/utils/schemaStrings.js +403 -0
- package/dist/utils/setupFiles.js +110 -61
- package/dist/utilsController.d.ts +40 -22
- package/dist/utilsController.js +164 -84
- package/package.json +13 -15
- package/src/collections/attributes.ts +483 -0
- package/src/collections/indexes.ts +53 -0
- package/src/collections/methods.ts +331 -0
- package/src/databases/methods.ts +47 -0
- package/src/init.ts +64 -64
- package/src/interactiveCLI.ts +767 -0
- package/src/main.ts +289 -83
- package/src/migrations/afterImportActions.ts +553 -490
- package/src/migrations/appwriteToX.ts +237 -174
- package/src/migrations/attributes.ts +483 -422
- package/src/migrations/backup.ts +205 -205
- package/src/migrations/collections.ts +545 -300
- package/src/migrations/converters.ts +161 -150
- package/src/migrations/dataLoader.ts +1615 -1304
- package/src/migrations/databases.ts +44 -25
- package/src/migrations/dbHelpers.ts +92 -92
- package/src/migrations/helper.ts +40 -0
- package/src/migrations/importController.ts +448 -384
- package/src/migrations/importDataActions.ts +315 -307
- package/src/migrations/indexes.ts +40 -37
- package/src/migrations/logging.ts +29 -16
- package/src/migrations/migrationHelper.ts +207 -201
- package/src/migrations/openapi.ts +83 -70
- package/src/migrations/queue.ts +118 -119
- package/src/migrations/relationships.ts +324 -324
- package/src/migrations/schemaStrings.ts +472 -460
- package/src/migrations/setupDatabase.ts +118 -219
- package/src/migrations/storage.ts +538 -358
- package/src/migrations/transfer.ts +608 -0
- package/src/migrations/users.ts +362 -285
- package/src/migrations/validationRules.ts +63 -63
- package/src/schemas/authUser.ts +23 -23
- package/src/setup.ts +8 -8
- package/src/storage/methods.ts +371 -0
- package/src/storage/schemas.ts +205 -0
- package/src/types.ts +9 -9
- package/src/utils/getClientFromConfig.ts +17 -0
- package/src/utils/helperFunctions.ts +181 -127
- package/src/utils/index.ts +2 -2
- package/src/utils/loadConfigs.ts +59 -59
- package/src/utils/retryFailedPromises.ts +27 -0
- package/src/utils/schemaStrings.ts +473 -0
- package/src/utils/setupFiles.ts +228 -182
- package/src/utilsController.ts +325 -194
- package/tsconfig.json +37 -37
@@ -1,384 +1,448 @@
|
|
1
|
-
import {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
type
|
6
|
-
type
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
import
|
16
|
-
import
|
17
|
-
import
|
18
|
-
import {
|
19
|
-
import {
|
20
|
-
import {
|
21
|
-
import {
|
22
|
-
import {
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
private
|
36
|
-
private
|
37
|
-
private
|
38
|
-
private
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
)
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
}
|
89
|
-
|
90
|
-
console.log(
|
91
|
-
console.log(
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
.
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
console.log(`
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
//
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
item.finalData
|
285
|
-
item.
|
286
|
-
context
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
)
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
//
|
365
|
-
//
|
366
|
-
//
|
367
|
-
//
|
368
|
-
//
|
369
|
-
//
|
370
|
-
//
|
371
|
-
//
|
372
|
-
//
|
373
|
-
//
|
374
|
-
//
|
375
|
-
//
|
376
|
-
//
|
377
|
-
|
378
|
-
|
379
|
-
//
|
380
|
-
//
|
381
|
-
//
|
382
|
-
//
|
383
|
-
//
|
384
|
-
|
1
|
+
import {
|
2
|
+
AppwriteException,
|
3
|
+
ID,
|
4
|
+
Query,
|
5
|
+
type Databases,
|
6
|
+
type Models,
|
7
|
+
type Storage,
|
8
|
+
} from "node-appwrite";
|
9
|
+
import type {
|
10
|
+
AppwriteConfig,
|
11
|
+
ConfigCollection,
|
12
|
+
ConfigDatabase,
|
13
|
+
AttributeMappings,
|
14
|
+
} from "appwrite-utils";
|
15
|
+
import type { ImportDataActions } from "./importDataActions.js";
|
16
|
+
import _ from "lodash";
|
17
|
+
import { areCollectionNamesSame, tryAwaitWithRetry } from "../utils/index.js";
|
18
|
+
import type { SetupOptions } from "../utilsController.js";
|
19
|
+
import { resolveAndUpdateRelationships } from "./relationships.js";
|
20
|
+
import { UsersController } from "./users.js";
|
21
|
+
import { logger } from "./logging.js";
|
22
|
+
import { updateOperation } from "./migrationHelper.js";
|
23
|
+
import {
|
24
|
+
BatchSchema,
|
25
|
+
OperationCreateSchema,
|
26
|
+
OperationSchema,
|
27
|
+
} from "./backup.js";
|
28
|
+
import { DataLoader, type CollectionImportData } from "./dataLoader.js";
|
29
|
+
import {
|
30
|
+
transferDatabaseLocalToLocal,
|
31
|
+
transferStorageLocalToLocal,
|
32
|
+
} from "./transfer.js";
|
33
|
+
|
34
|
+
export class ImportController {
|
35
|
+
private config: AppwriteConfig;
|
36
|
+
private database: Databases;
|
37
|
+
private storage: Storage;
|
38
|
+
private appwriteFolderPath: string;
|
39
|
+
private importDataActions: ImportDataActions;
|
40
|
+
private setupOptions: SetupOptions;
|
41
|
+
private documentCache: Map<string, any>;
|
42
|
+
private batchLimit: number = 25; // Define batch size limit
|
43
|
+
private hasImportedUsers = false;
|
44
|
+
private postImportActionsQueue: {
|
45
|
+
context: any;
|
46
|
+
finalItem: any;
|
47
|
+
attributeMappings: AttributeMappings;
|
48
|
+
}[] = [];
|
49
|
+
private databasesToRun: Models.Database[];
|
50
|
+
|
51
|
+
constructor(
|
52
|
+
config: AppwriteConfig,
|
53
|
+
database: Databases,
|
54
|
+
storage: Storage,
|
55
|
+
appwriteFolderPath: string,
|
56
|
+
importDataActions: ImportDataActions,
|
57
|
+
setupOptions: SetupOptions,
|
58
|
+
databasesToRun?: Models.Database[]
|
59
|
+
) {
|
60
|
+
this.config = config;
|
61
|
+
this.database = database;
|
62
|
+
this.storage = storage;
|
63
|
+
this.appwriteFolderPath = appwriteFolderPath;
|
64
|
+
this.importDataActions = importDataActions;
|
65
|
+
this.setupOptions = setupOptions;
|
66
|
+
this.documentCache = new Map();
|
67
|
+
this.databasesToRun = databasesToRun || [];
|
68
|
+
}
|
69
|
+
|
70
|
+
async run() {
|
71
|
+
let databasesToProcess: Models.Database[];
|
72
|
+
|
73
|
+
if (this.databasesToRun.length > 0) {
|
74
|
+
// Use the provided databases
|
75
|
+
databasesToProcess = this.databasesToRun;
|
76
|
+
} else {
|
77
|
+
// If no databases are specified, fetch all databases
|
78
|
+
const allDatabases = await this.database.list();
|
79
|
+
databasesToProcess = allDatabases.databases;
|
80
|
+
}
|
81
|
+
|
82
|
+
let dataLoader: DataLoader | undefined;
|
83
|
+
let databaseRan: Models.Database | undefined;
|
84
|
+
|
85
|
+
for (let db of databasesToProcess) {
|
86
|
+
if (db.name.toLowerCase().trim().replace(" ", "") === "migrations") {
|
87
|
+
continue;
|
88
|
+
}
|
89
|
+
|
90
|
+
console.log(`---------------------------------`);
|
91
|
+
console.log(`Starting import data for database: ${db.name}`);
|
92
|
+
console.log(`---------------------------------`);
|
93
|
+
|
94
|
+
if (!databaseRan) {
|
95
|
+
databaseRan = db;
|
96
|
+
dataLoader = new DataLoader(
|
97
|
+
this.appwriteFolderPath,
|
98
|
+
this.importDataActions,
|
99
|
+
this.database,
|
100
|
+
this.config,
|
101
|
+
this.setupOptions.shouldWriteFile
|
102
|
+
);
|
103
|
+
await dataLoader.start(db.$id);
|
104
|
+
await this.importCollections(db, dataLoader);
|
105
|
+
await resolveAndUpdateRelationships(db.$id, this.database, this.config);
|
106
|
+
await this.executePostImportActions(db.$id, dataLoader);
|
107
|
+
} else if (databaseRan.$id !== db.$id) {
|
108
|
+
await this.updateOthersToFinalData(databaseRan, db);
|
109
|
+
}
|
110
|
+
|
111
|
+
console.log(`---------------------------------`);
|
112
|
+
console.log(`Finished import data for database: ${db.name}`);
|
113
|
+
console.log(`---------------------------------`);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
async updateOthersToFinalData(
|
118
|
+
updatedDb: Models.Database,
|
119
|
+
targetDb: Models.Database
|
120
|
+
) {
|
121
|
+
await transferDatabaseLocalToLocal(
|
122
|
+
this.database,
|
123
|
+
updatedDb.$id,
|
124
|
+
targetDb.$id
|
125
|
+
);
|
126
|
+
|
127
|
+
// Find the corresponding database configs
|
128
|
+
const updatedDbConfig = this.config.databases.find(
|
129
|
+
(db) => db.$id === updatedDb.$id
|
130
|
+
);
|
131
|
+
const targetDbConfig = this.config.databases.find(
|
132
|
+
(db) => db.$id === targetDb.$id
|
133
|
+
);
|
134
|
+
|
135
|
+
// Transfer database-specific bucket if both databases have a bucket defined
|
136
|
+
if (updatedDbConfig?.bucket && targetDbConfig?.bucket) {
|
137
|
+
await transferStorageLocalToLocal(
|
138
|
+
this.storage,
|
139
|
+
updatedDbConfig.bucket.$id,
|
140
|
+
targetDbConfig.bucket.$id
|
141
|
+
);
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
async importCollections(db: ConfigDatabase, dataLoader: DataLoader) {
|
146
|
+
if (!this.config.collections) {
|
147
|
+
return;
|
148
|
+
}
|
149
|
+
for (const collection of this.config.collections) {
|
150
|
+
let isUsersCollection =
|
151
|
+
dataLoader.getCollectionKey(this.config.usersCollectionName) ===
|
152
|
+
dataLoader.getCollectionKey(collection.name);
|
153
|
+
const importOperationId = dataLoader.collectionImportOperations.get(
|
154
|
+
dataLoader.getCollectionKey(collection.name)
|
155
|
+
);
|
156
|
+
const createBatches = (finalData: CollectionImportData["data"]) => {
|
157
|
+
let maxBatchLength = 100;
|
158
|
+
const finalBatches: CollectionImportData["data"][] = [];
|
159
|
+
for (let i = 0; i < finalData.length; i++) {
|
160
|
+
if (i % maxBatchLength === 0) {
|
161
|
+
finalBatches.push([]);
|
162
|
+
}
|
163
|
+
finalBatches[finalBatches.length - 1].push(finalData[i]);
|
164
|
+
}
|
165
|
+
return finalBatches;
|
166
|
+
};
|
167
|
+
|
168
|
+
if (isUsersCollection && !this.hasImportedUsers) {
|
169
|
+
const usersDataMap = dataLoader.importMap.get(
|
170
|
+
dataLoader.getCollectionKey("users")
|
171
|
+
);
|
172
|
+
const usersData = usersDataMap?.data;
|
173
|
+
const usersController = new UsersController(this.config, this.database);
|
174
|
+
if (usersData) {
|
175
|
+
console.log("Found users data", usersData.length);
|
176
|
+
const userDataBatches = createBatches(usersData);
|
177
|
+
for (const batch of userDataBatches) {
|
178
|
+
console.log("Importing users batch", batch.length);
|
179
|
+
const userBatchPromises = batch
|
180
|
+
.filter((item) => {
|
181
|
+
let itemId: string | undefined;
|
182
|
+
if (item.finalData.userId) {
|
183
|
+
itemId = item.finalData.userId;
|
184
|
+
} else if (item.finalData.docId) {
|
185
|
+
itemId = item.finalData.docId;
|
186
|
+
}
|
187
|
+
if (!itemId) {
|
188
|
+
return false;
|
189
|
+
}
|
190
|
+
return (
|
191
|
+
item &&
|
192
|
+
item.finalData &&
|
193
|
+
!dataLoader.userExistsMap.has(itemId)
|
194
|
+
);
|
195
|
+
})
|
196
|
+
.map((item) => {
|
197
|
+
dataLoader.userExistsMap.set(
|
198
|
+
item.finalData.userId ||
|
199
|
+
item.finalData.docId ||
|
200
|
+
item.context.userId ||
|
201
|
+
item.context.docId,
|
202
|
+
true
|
203
|
+
);
|
204
|
+
return usersController.createUserAndReturn(item.finalData);
|
205
|
+
});
|
206
|
+
const promiseResults = await Promise.allSettled(userBatchPromises);
|
207
|
+
for (const item of batch) {
|
208
|
+
if (item && item.finalData) {
|
209
|
+
dataLoader.userExistsMap.set(
|
210
|
+
item.finalData.userId ||
|
211
|
+
item.finalData.docId ||
|
212
|
+
item.context.userId ||
|
213
|
+
item.context.docId,
|
214
|
+
true
|
215
|
+
);
|
216
|
+
}
|
217
|
+
}
|
218
|
+
console.log("Finished importing users batch");
|
219
|
+
}
|
220
|
+
this.hasImportedUsers = true;
|
221
|
+
console.log("Finished importing users");
|
222
|
+
}
|
223
|
+
}
|
224
|
+
|
225
|
+
if (!importOperationId) {
|
226
|
+
// Skip further processing if no import operation is found
|
227
|
+
continue;
|
228
|
+
}
|
229
|
+
|
230
|
+
const importOperation = await this.database.getDocument(
|
231
|
+
"migrations",
|
232
|
+
"currentOperations",
|
233
|
+
importOperationId
|
234
|
+
);
|
235
|
+
await updateOperation(this.database, importOperation.$id, {
|
236
|
+
status: "in_progress",
|
237
|
+
});
|
238
|
+
const collectionData = dataLoader.importMap.get(
|
239
|
+
dataLoader.getCollectionKey(collection.name)
|
240
|
+
);
|
241
|
+
console.log(`Processing collection: ${collection.name}...`);
|
242
|
+
if (!collectionData) {
|
243
|
+
console.log("No collection data for ", collection.name);
|
244
|
+
continue;
|
245
|
+
}
|
246
|
+
|
247
|
+
const dataSplit = createBatches(collectionData.data);
|
248
|
+
let processedItems = 0;
|
249
|
+
for (let i = 0; i < dataSplit.length; i++) {
|
250
|
+
const batches = dataSplit[i];
|
251
|
+
console.log(`Processing batch ${i + 1} of ${dataSplit.length}`);
|
252
|
+
|
253
|
+
// const documentExistsPromises = batches.map(async (item) => {
|
254
|
+
// try {
|
255
|
+
// const id =
|
256
|
+
// item.finalData.docId ||
|
257
|
+
// item.finalData.userId ||
|
258
|
+
// item.context.docId ||
|
259
|
+
// item.context.userId;
|
260
|
+
|
261
|
+
// if (!item.finalData) {
|
262
|
+
// return Promise.resolve(null);
|
263
|
+
// }
|
264
|
+
// return tryAwaitWithRetry(
|
265
|
+
// async () =>
|
266
|
+
// await documentExists(
|
267
|
+
// this.database,
|
268
|
+
// db.$id,
|
269
|
+
// collection.$id,
|
270
|
+
// item.finalData
|
271
|
+
// )
|
272
|
+
// );
|
273
|
+
// } catch (error) {
|
274
|
+
// console.error(error);
|
275
|
+
// return Promise.resolve(null);
|
276
|
+
// }
|
277
|
+
// });
|
278
|
+
|
279
|
+
// const documentExistsResults = await Promise.all(documentExistsPromises);
|
280
|
+
|
281
|
+
const batchPromises = batches.map((item, index) => {
|
282
|
+
try {
|
283
|
+
const id =
|
284
|
+
item.finalData.docId ||
|
285
|
+
item.finalData.userId ||
|
286
|
+
item.context.docId ||
|
287
|
+
item.context.userId;
|
288
|
+
|
289
|
+
if (item.finalData.hasOwnProperty("userId")) {
|
290
|
+
delete item.finalData.userId;
|
291
|
+
}
|
292
|
+
if (item.finalData.hasOwnProperty("docId")) {
|
293
|
+
delete item.finalData.docId;
|
294
|
+
}
|
295
|
+
if (!item.finalData) {
|
296
|
+
return Promise.resolve();
|
297
|
+
}
|
298
|
+
return tryAwaitWithRetry(
|
299
|
+
async () =>
|
300
|
+
await this.database.createDocument(
|
301
|
+
db.$id,
|
302
|
+
collection.$id,
|
303
|
+
id,
|
304
|
+
item.finalData
|
305
|
+
)
|
306
|
+
);
|
307
|
+
} catch (error) {
|
308
|
+
console.error(error);
|
309
|
+
return Promise.resolve();
|
310
|
+
}
|
311
|
+
});
|
312
|
+
|
313
|
+
// Wait for all promises in the current batch to resolve
|
314
|
+
await Promise.all(batchPromises);
|
315
|
+
console.log(`Completed batch ${i + 1} of ${dataSplit.length}`);
|
316
|
+
await updateOperation(this.database, importOperation.$id, {
|
317
|
+
progress: processedItems,
|
318
|
+
});
|
319
|
+
}
|
320
|
+
// After all batches are processed, update the operation status to completed
|
321
|
+
await updateOperation(this.database, importOperation.$id, {
|
322
|
+
status: "completed",
|
323
|
+
});
|
324
|
+
}
|
325
|
+
}
|
326
|
+
|
327
|
+
async executePostImportActions(dbId: string, dataLoader: DataLoader) {
|
328
|
+
// Iterate over each collection in the importMap
|
329
|
+
for (const [
|
330
|
+
collectionKey,
|
331
|
+
collectionData,
|
332
|
+
] of dataLoader.importMap.entries()) {
|
333
|
+
console.log(
|
334
|
+
`Processing post-import actions for collection: ${collectionKey}`
|
335
|
+
);
|
336
|
+
|
337
|
+
// Iterate over each item in the collectionData.data
|
338
|
+
for (const item of collectionData.data) {
|
339
|
+
// Assuming each item has attributeMappings that contain actions to be executed
|
340
|
+
if (item.importDef && item.importDef.attributeMappings) {
|
341
|
+
// Use item.context as the context for action execution
|
342
|
+
const context = item.context; // Directly use item.context as the context for action execution
|
343
|
+
// Iterate through attributeMappings to execute actions
|
344
|
+
try {
|
345
|
+
// Execute post-import actions for the current attributeMapping
|
346
|
+
// Pass item.finalData as the data to be processed along with the context
|
347
|
+
await this.importDataActions.executeAfterImportActions(
|
348
|
+
item.finalData,
|
349
|
+
item.importDef.attributeMappings,
|
350
|
+
context
|
351
|
+
);
|
352
|
+
} catch (error) {
|
353
|
+
console.error(
|
354
|
+
`Failed to execute post-import actions for item in collection ${collectionKey}:`,
|
355
|
+
error
|
356
|
+
);
|
357
|
+
// Handle error (e.g., log, retry, continue with next action)
|
358
|
+
}
|
359
|
+
}
|
360
|
+
}
|
361
|
+
}
|
362
|
+
}
|
363
|
+
|
364
|
+
// async executeActionsInParallel(dbId: string, collection: ConfigCollection) {
|
365
|
+
// const collectionExists = await checkForCollection(
|
366
|
+
// this.database,
|
367
|
+
// dbId,
|
368
|
+
// collection
|
369
|
+
// );
|
370
|
+
// if (!collectionExists) {
|
371
|
+
// logger.error(`No collection found for ${collection.name}`);
|
372
|
+
// return; // Skip this iteration
|
373
|
+
// }
|
374
|
+
// const operations = await getAfterImportOperations(
|
375
|
+
// this.database,
|
376
|
+
// collectionExists.$id
|
377
|
+
// );
|
378
|
+
|
379
|
+
// for (const operation of operations) {
|
380
|
+
// if (!operation.batches) {
|
381
|
+
// continue;
|
382
|
+
// }
|
383
|
+
// const batches = operation.batches;
|
384
|
+
// const promises = [];
|
385
|
+
// for (const batch of batches) {
|
386
|
+
// const batchId = batch;
|
387
|
+
// promises.push(
|
388
|
+
// this.database.getDocument("migrations", "batches", batchId)
|
389
|
+
// );
|
390
|
+
// }
|
391
|
+
// const results = await Promise.allSettled(promises);
|
392
|
+
// results.forEach((result) => {
|
393
|
+
// if (result.status === "rejected") {
|
394
|
+
// logger.error("A process batch promise was rejected:", result.reason);
|
395
|
+
// }
|
396
|
+
// });
|
397
|
+
// const resultsData = results
|
398
|
+
// .map((result) => (result.status === "fulfilled" ? result.value : null))
|
399
|
+
// .filter((result: any) => result !== null && !result.processed)
|
400
|
+
// .map((result) => BatchSchema.parse(result));
|
401
|
+
// for (const batch of resultsData) {
|
402
|
+
// const actionOperation = ContextObject.parse(JSON.parse(batch.data));
|
403
|
+
// const { context, finalItem, attributeMappings } = actionOperation;
|
404
|
+
// if (finalItem.$id && !context.docId) {
|
405
|
+
// context.docId =
|
406
|
+
// finalItem.$id || context.createdDoc.$id || context.$id || undefined;
|
407
|
+
// logger.info(
|
408
|
+
// `Setting docId to ${
|
409
|
+
// finalItem.$id
|
410
|
+
// } because docId not found in context, batch ${
|
411
|
+
// batch.$id
|
412
|
+
// }, context is ${JSON.stringify(context)}`
|
413
|
+
// );
|
414
|
+
// }
|
415
|
+
// try {
|
416
|
+
// await this.importDataActions.executeAfterImportActions(
|
417
|
+
// finalItem,
|
418
|
+
// attributeMappings,
|
419
|
+
// context
|
420
|
+
// );
|
421
|
+
// // Mark batch as processed
|
422
|
+
// await this.database.deleteDocument(
|
423
|
+
// "migrations",
|
424
|
+
// "batches",
|
425
|
+
// batch.$id
|
426
|
+
// );
|
427
|
+
// } catch (error) {
|
428
|
+
// logger.error(
|
429
|
+
// `Failed to execute batch ${batch.$id}:`,
|
430
|
+
// error,
|
431
|
+
// "Context is :",
|
432
|
+
// context
|
433
|
+
// );
|
434
|
+
// await this.database.deleteDocument(
|
435
|
+
// "migrations",
|
436
|
+
// "batches",
|
437
|
+
// batch.$id
|
438
|
+
// );
|
439
|
+
// }
|
440
|
+
// }
|
441
|
+
|
442
|
+
// // After processing all batches, update the operation status
|
443
|
+
// await updateOperation(this.database, operation.$id, {
|
444
|
+
// status: "completed", // Or determine based on batch success/failure
|
445
|
+
// });
|
446
|
+
// }
|
447
|
+
// }
|
448
|
+
}
|