@aneuhold/be-ts-db-lib 3.0.0 → 3.0.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.
Files changed (26) hide show
  1. package/CHANGELOG.md +19 -1
  2. package/lib/repositories/BaseRepository.d.ts +1 -1
  3. package/lib/repositories/BaseRepository.d.ts.map +1 -1
  4. package/lib/repositories/BaseRepository.js.map +1 -1
  5. package/lib/repositories/BaseRepository.ts +2 -2
  6. package/lib/repositories/dashboard/DashboardNonogramKatanaItemRepository.d.ts.map +1 -1
  7. package/lib/repositories/dashboard/DashboardNonogramKatanaItemRepository.js +7 -3
  8. package/lib/repositories/dashboard/DashboardNonogramKatanaItemRepository.js.map +1 -1
  9. package/lib/repositories/dashboard/DashboardNonogramKatanaItemRepository.ts +9 -3
  10. package/lib/repositories/dashboard/DashboardNonogramKatanaUpgradeRepository.d.ts.map +1 -1
  11. package/lib/repositories/dashboard/DashboardNonogramKatanaUpgradeRepository.js +7 -3
  12. package/lib/repositories/dashboard/DashboardNonogramKatanaUpgradeRepository.js.map +1 -1
  13. package/lib/repositories/dashboard/DashboardNonogramKatanaUpgradeRepository.ts +10 -4
  14. package/lib/repositories/dashboard/DashboardTaskRepository.d.ts.map +1 -1
  15. package/lib/repositories/dashboard/DashboardTaskRepository.js +6 -5
  16. package/lib/repositories/dashboard/DashboardTaskRepository.js.map +1 -1
  17. package/lib/repositories/dashboard/DashboardTaskRepository.ts +7 -6
  18. package/lib/repositories/dashboard/DashboardUserConfigRepository.d.ts.map +1 -1
  19. package/lib/repositories/dashboard/DashboardUserConfigRepository.js +9 -10
  20. package/lib/repositories/dashboard/DashboardUserConfigRepository.js.map +1 -1
  21. package/lib/repositories/dashboard/DashboardUserConfigRepository.ts +16 -14
  22. package/lib/services/MigrationService.d.ts.map +1 -1
  23. package/lib/services/MigrationService.js +308 -129
  24. package/lib/services/MigrationService.js.map +1 -1
  25. package/lib/services/MigrationService.ts +379 -135
  26. package/package.json +6 -5
@@ -1,9 +1,20 @@
1
1
  /* eslint-disable */
2
2
  // @ts-nocheck
3
+ import {
4
+ ApiKey,
5
+ DashboardTask,
6
+ DashboardUserConfig,
7
+ DocumentService,
8
+ NonogramKatanaItem,
9
+ NonogramKatanaUpgrade,
10
+ User
11
+ } from '@aneuhold/core-ts-db-lib';
3
12
  import { DR } from '@aneuhold/core-ts-lib';
4
- import { ObjectId } from 'bson';
5
13
  import { v7 as uuidv7 } from 'uuid';
14
+ import ApiKeyRepository from '../repositories/common/ApiKeyRepository.js';
6
15
  import UserRepository from '../repositories/common/UserRepository.js';
16
+ import DashboardNonogramKatanaItemRepository from '../repositories/dashboard/DashboardNonogramKatanaItemRepository.js';
17
+ import DashboardNonogramKatanaUpgradeRepository from '../repositories/dashboard/DashboardNonogramKatanaUpgradeRepository.js';
7
18
  import DashboardTaskRepository from '../repositories/dashboard/DashboardTaskRepository.js';
8
19
  import DashboardUserConfigRepository from '../repositories/dashboard/DashboardUserConfigRepository.js';
9
20
 
@@ -25,185 +36,418 @@ export default class MigrationService {
25
36
  * @param dryRun Whether or not to actually make the changes or just log them.
26
37
  */
27
38
  static async migrateDb(dryRun = false): Promise<void> {
28
- return;
29
- DR.logger.info('Starting migration from ObjectId to UUID v7...');
39
+ DR.logger.info('Starting migration...');
30
40
 
31
41
  // 1. Load all documents
32
42
  const userRepo = UserRepository.getRepo();
43
+ const apiKeyRepo = ApiKeyRepository.getRepo();
33
44
  const taskRepo = DashboardTaskRepository.getRepo();
34
45
  const configRepo = DashboardUserConfigRepository.getRepo();
46
+ const nonogramItemRepo = DashboardNonogramKatanaItemRepository.getRepo();
47
+ const nonogramUpgradesRepo = DashboardNonogramKatanaUpgradeRepository.getRepo();
35
48
 
36
49
  const users = await userRepo.getAll();
50
+ const apiKeys = await apiKeyRepo.getAll();
37
51
  const tasks = await taskRepo.getAll();
38
52
  const configs = await configRepo.getAll();
53
+ const nonogramItems = await nonogramItemRepo.getAll();
54
+ const nonogramUpgrades = await nonogramUpgradesRepo.getAll();
39
55
 
40
- DR.logger.info(`Loaded ${users.length} users, ${tasks.length} tasks, ${configs.length} configs.`);
41
-
42
- // 2. Create ID Map (Old ObjectId string -> New UUID)
43
- const idMap = new Map<string, string>();
44
- let newIdCount = 0;
56
+ DR.logger.info(
57
+ `Loaded ${users.length} users, ${apiKeys.length} API keys, ${tasks.length} tasks, ${configs.length} configs, ${nonogramItems.length} nonogram items, and ${nonogramUpgrades.length} nonogram upgrades.`
58
+ );
45
59
 
46
- const addToMap = (docs: any[]) => {
60
+ const countObjectIds = (docs: any[]) => {
47
61
  docs.forEach((doc) => {
48
- if (doc._id instanceof ObjectId) {
49
- idMap.set(doc._id.toHexString(), uuidv7());
50
- newIdCount++;
51
- } else if (typeof doc._id === 'string' && !idMap.has(doc._id)) {
52
- // Already a string? Maybe already migrated or just a string ID.
53
- // If it looks like an ObjectId, map it.
54
- if (ObjectId.isValid(doc._id) && doc._id.length === 24) {
55
- idMap.set(doc._id, uuidv7());
56
- newIdCount++;
57
- }
58
- }
62
+ // Get the type of the _id field
63
+ console.log(`Document ID type: ${typeof doc._id}, value: ${doc._id}`);
59
64
  });
60
65
  };
61
66
 
62
- addToMap(users);
63
- addToMap(tasks);
64
- addToMap(configs);
65
-
66
- DR.logger.info(`Generated ${newIdCount} new UUIDs.`);
67
+ // Create a map of document IDs to new UUIDs
68
+ const allDocs = [
69
+ ...users,
70
+ ...apiKeys,
71
+ ...tasks,
72
+ ...configs,
73
+ ...nonogramItems,
74
+ ...nonogramUpgrades
75
+ ];
76
+ const legacyDocs = allDocs.filter((doc) => typeof doc._id === 'object');
77
+ const newDocs = allDocs.filter((doc) => typeof doc._id === 'string');
78
+
79
+ DR.logger.info(
80
+ `Found ${legacyDocs.length} documents with legacy ObjectId IDs and ${newDocs.length} documents with string IDs.`
81
+ );
82
+
83
+ // Delete all existing new docs (with string IDs) to ensure fresh creation
84
+ if (!dryRun && newDocs.length > 0) {
85
+ DR.logger.info(`Deleting ${newDocs.length} existing migrated documents...`);
86
+ const newDocIds = newDocs.map((doc) => doc._id);
87
+
88
+ const userIdsToDelete = users.filter((u) => typeof u._id === 'string').map((u) => u._id);
89
+ const apiKeyIdsToDelete = apiKeys.filter((k) => typeof k._id === 'string').map((k) => k._id);
90
+ const taskIdsToDelete = tasks.filter((t) => typeof t._id === 'string').map((t) => t._id);
91
+ const configIdsToDelete = configs.filter((c) => typeof c._id === 'string').map((c) => c._id);
92
+ const nonogramItemIdsToDelete = nonogramItems.filter((i) => typeof i._id === 'string').map((i) => i._id);
93
+ const nonogramUpgradeIdsToDelete = nonogramUpgrades.filter((u) => typeof u._id === 'string').map((u) => u._id);
94
+
95
+ if (userIdsToDelete.length > 0) {
96
+ const result = await (await userRepo.getCollection()).deleteMany({ _id: { $in: userIdsToDelete } });
97
+ DR.logger.info(`Deleted ${result.deletedCount} users.`);
98
+ }
99
+ if (apiKeyIdsToDelete.length > 0) {
100
+ const result = await (await apiKeyRepo.getCollection()).deleteMany({ _id: { $in: apiKeyIdsToDelete } });
101
+ DR.logger.info(`Deleted ${result.deletedCount} API keys.`);
102
+ }
103
+ if (taskIdsToDelete.length > 0) {
104
+ const result = await (await taskRepo.getCollection()).deleteMany({ _id: { $in: taskIdsToDelete } });
105
+ DR.logger.info(`Deleted ${result.deletedCount} tasks.`);
106
+ }
107
+ if (configIdsToDelete.length > 0) {
108
+ const result = await (await configRepo.getCollection()).deleteMany({ _id: { $in: configIdsToDelete } });
109
+ DR.logger.info(`Deleted ${result.deletedCount} configs.`);
110
+ }
111
+ if (nonogramItemIdsToDelete.length > 0) {
112
+ const result = await (await nonogramItemRepo.getCollection()).deleteMany({ _id: { $in: nonogramItemIdsToDelete } });
113
+ DR.logger.info(`Deleted ${result.deletedCount} nonogram items.`);
114
+ }
115
+ if (nonogramUpgradeIdsToDelete.length > 0) {
116
+ const result = await (await nonogramUpgradesRepo.getCollection()).deleteMany({ _id: { $in: nonogramUpgradeIdsToDelete } });
117
+ DR.logger.info(`Deleted ${result.deletedCount} nonogram upgrades.`);
118
+ }
119
+
120
+ DR.logger.info('Deletion complete. Starting fresh migration...');
121
+ } else if (dryRun && newDocs.length > 0) {
122
+ DR.logger.info(`Dry run: Would delete ${newDocs.length} existing migrated documents.`);
123
+ }
67
124
 
68
- // 3. Helper to get new ID
69
- const getNewId = (oldId: any): string | undefined => {
70
- if (!oldId) return undefined;
125
+ // Now create the actual map
126
+ const mapFromObjectIdToUUID = new Map<string, UUID>();
127
+
128
+ const newUsersToCreate: User[] = [];
129
+ const newApiKeysToCreate: ApiKey[] = [];
130
+ const newTasksToCreate: DashboardTask[] = [];
131
+ const newConfigsToCreate: DashboardUserConfig[] = [];
132
+ const newNonogramItemsToCreate: NonogramKatanaItem[] = [];
133
+ const newNonogramUpgradesToCreate: NonogramKatanaUpgrade[] = [];
134
+
135
+ /**
136
+ * Gets a UUID for a given legacy ObjectId. If one already exists in the map,
137
+ * it is returned. Otherwise, a new one is generated and added to the map.
138
+ */
139
+ const getUUID = (oldId: ObjectId): UUID => {
71
140
  const oldIdStr = oldId.toString();
72
- return idMap.get(oldIdStr) || (typeof oldId === 'string' ? oldId : undefined);
141
+ if (mapFromObjectIdToUUID.has(oldIdStr)) {
142
+ return mapFromObjectIdToUUID.get(oldIdStr);
143
+ }
144
+ const newId = uuidv7();
145
+ mapFromObjectIdToUUID.set(oldIdStr, newId);
146
+ return newId;
73
147
  };
74
148
 
75
- // 4. Prepare New Documents
76
- const newUsers: any[] = [];
77
- const oldUserIds: ObjectId[] = [];
78
-
79
- const newTasks: any[] = [];
80
- const oldTaskIds: ObjectId[] = [];
81
-
82
- const newConfigs: any[] = [];
83
- const oldConfigIds: ObjectId[] = [];
84
-
85
- // --- Process Users ---
86
- for (const user of users) {
87
- if (user._id instanceof ObjectId) {
88
- const newId = getNewId(user._id);
89
- if (!newId) continue;
90
-
91
- const newUser = { ...user, _id: newId };
92
- // Users don't have many internal refs usually, but check if needed
93
- newUsers.push(newUser);
94
- oldUserIds.push(user._id);
149
+ // Create a map of UUID to documents
150
+ const mapFromUUIDToDocument = new Map<UUID, any>();
151
+
152
+ const verifyDoc = (oldDoc: any, newDoc: any) => {
153
+ const oldJson = JSON.stringify(oldDoc, null, 2);
154
+ const newJson = JSON.stringify(newDoc, null, 2);
155
+ const oldLines = oldJson.split('\n').length;
156
+ const newLines = newJson.split('\n').length;
157
+ if (newLines !== oldLines + 1) {
158
+ DR.logger.warn(
159
+ `Line count mismatch for ${oldDoc.docType || 'doc'} ${oldDoc._id}: Old=${oldLines}, New=${newLines}.`
160
+ );
161
+ }
162
+ };
163
+
164
+ function createNewDoc(oldDoc) {
165
+ if (mapFromObjectIdToUUID.has(oldDoc._id.toString()) && mapFromUUIDToDocument.has(mapFromObjectIdToUUID.get(oldDoc._id.toString()))) {
166
+ console.warn(
167
+ `Skipping document ${oldDoc._id} as it was already migrated.` +
168
+ ` The created document is ${JSON.stringify(mapFromUUIDToDocument.get(mapFromObjectIdToUUID.get(oldDoc._id.toString())))}`
169
+ );
170
+ return;
95
171
  }
172
+ const newDocId = getUUID(oldDoc._id);
173
+ const newDoc = DocumentService.deepCopy(oldDoc);
174
+ newDoc._id = newDocId;
175
+ newDoc.oldOId = oldDoc._id.toString();
176
+ mapFromUUIDToDocument.set(newDocId, newDoc);
177
+ return newDoc;
96
178
  }
97
179
 
98
- // --- Process Tasks ---
99
- for (const task of tasks) {
100
- if (task._id instanceof ObjectId) {
101
- const newId = getNewId(task._id);
102
- if (!newId) continue;
180
+ // Filter to only legacy users with the chosen usernames
181
+ const userNames = ['demoUser1', 'demoUser2', "testUser", "testUser2"];
182
+ // const userNames = ["testUser"];
183
+ const legacyUsers = users.filter((u) => userNames.includes(u.userName) && typeof u._id === 'object');
184
+ DR.logger.info(`Found ${legacyUsers.length} legacy users to migrate.`);
185
+
186
+ // First, create all user documents and generate their UUIDs that way relationships between
187
+ // users in the collaborators field can be mapped correctly.
188
+ legacyUsers.forEach((oldUserDoc) => {
189
+ const newUser = createNewDoc(oldUserDoc);
190
+ if (!newUser) return;
191
+ verifyDoc(oldUserDoc, newUser);
192
+ newUsersToCreate.push(newUser);
193
+ });
194
+
195
+ // Create the function that will flesh out new documents for a given user document
196
+ function createNewDocsForUser(oldUserDoc: User) {
197
+ const oldUserIdStr = oldUserDoc._id.toString();
198
+ const newUserId = getUUID(oldUserDoc._id);
199
+
200
+ // 1. Create new API keys
201
+ const userApiKeys = apiKeys.filter((k) => k.userId.toString() === oldUserIdStr);
202
+ userApiKeys.forEach((oldKey) => {
203
+ const newKey = createNewDoc(oldKey);
204
+ if (!newKey) return;
205
+ newKey.userId = newUserId;
206
+ verifyDoc(oldKey, newKey);
207
+ newApiKeysToCreate.push(newKey);
208
+ });
103
209
 
104
- const newTask = { ...task, _id: newId };
210
+ // 2. Create new Tasks
211
+ const userTasks = tasks.filter(
212
+ (t) => t.userId.toString() === oldUserIdStr
213
+ );
105
214
 
106
- // Fix userId
107
- if (newTask.userId) newTask.userId = getNewId(newTask.userId) || newTask.userId;
215
+ const taskChildrenMap = new Map<string, DashboardTask[]>();
216
+ const rootTasks: DashboardTask[] = [];
217
+ const userTaskIds = new Set(userTasks.map((t) => t._id.toString()));
108
218
 
109
- // Fix assignedTo
110
- if (newTask.assignedTo) newTask.assignedTo = getNewId(newTask.assignedTo) || newTask.assignedTo;
219
+ userTasks.forEach((task) => {
220
+ const pId = task.parentTaskId?.toString();
221
+ if (pId && userTaskIds.has(pId)) {
222
+ if (!taskChildrenMap.has(pId)) {
223
+ taskChildrenMap.set(pId, []);
224
+ }
225
+ taskChildrenMap.get(pId).push(task);
226
+ } else {
227
+ rootTasks.push(task);
228
+ }
229
+ });
111
230
 
112
- // Fix parentTaskId
113
- if (newTask.parentTaskId) newTask.parentTaskId = getNewId(newTask.parentTaskId) || newTask.parentTaskId;
231
+ const queue = [...rootTasks];
232
+ while (queue.length > 0) {
233
+ const oldTask = queue.shift()!;
234
+ const newTask = createNewDoc(oldTask);
114
235
 
115
- // Fix sharedWith array
116
- if (Array.isArray(newTask.sharedWith)) {
117
- newTask.sharedWith = newTask.sharedWith.map((id: any) => getNewId(id) || id);
118
- }
236
+ if (newTask) {
237
+ newTask.userId = newUserId;
119
238
 
120
- // Fix tags keys (userIds are keys)
121
- if (newTask.tags) {
239
+ // Map user IDs in tags keys
122
240
  const newTags: any = {};
123
- for (const [key, val] of Object.entries(newTask.tags)) {
124
- const newKey = getNewId(key) || key;
125
- newTags[newKey] = val;
126
- }
241
+ Object.keys(oldTask.tags).forEach((tagUserId) => {
242
+ const newTagUserId = getUUID(tagUserId);
243
+ newTags[newTagUserId] = oldTask.tags[tagUserId];
244
+ });
127
245
  newTask.tags = newTags;
128
- }
129
-
130
- // Fix filterSettings keys (userIds are keys)
131
- if (newTask.filterSettings) {
132
- const newSettings: any = {};
133
- for (const [key, val] of Object.entries(newTask.filterSettings)) {
134
- const newKey = getNewId(key) || key;
135
- newSettings[newKey] = val;
136
- }
137
- newTask.filterSettings = newSettings;
138
- }
139
246
 
140
- // Fix sortSettings keys (userIds are keys)
141
- if (newTask.sortSettings) {
142
- const newSettings: any = {};
143
- for (const [key, val] of Object.entries(newTask.sortSettings)) {
144
- const newKey = getNewId(key) || key;
145
- newSettings[newKey] = val;
247
+ // Map user IDs in filterSettings keys
248
+ const newFilterSettings: any = {};
249
+ Object.keys(oldTask.filterSettings).forEach((fsUserId) => {
250
+ const newFsUserId = getUUID(fsUserId);
251
+ newFilterSettings[newFsUserId] = {
252
+ ...oldTask.filterSettings[fsUserId],
253
+ userId: newFsUserId
254
+ };
255
+ });
256
+ newTask.filterSettings = newFilterSettings;
257
+
258
+ // Map user IDs in sortSettings keys
259
+ const newSortSettings: any = {};
260
+ Object.keys(oldTask.sortSettings).forEach((ssUserId) => {
261
+ const newSsUserId = getUUID(ssUserId);
262
+ newSortSettings[newSsUserId] = {
263
+ ...oldTask.sortSettings[ssUserId],
264
+ userId: newSsUserId
265
+ };
266
+ });
267
+ newTask.sortSettings = newSortSettings;
268
+
269
+ newTask.sharedWith = oldTask.sharedWith.map((id: any) => getUUID(id));
270
+ if (oldTask.assignedTo) {
271
+ newTask.assignedTo = getUUID(oldTask.assignedTo);
272
+ }
273
+ if (oldTask.parentTaskId) {
274
+ newTask.parentTaskId = getUUID(oldTask.parentTaskId);
146
275
  }
147
- newTask.sortSettings = newSettings;
276
+ if (oldTask.parentRecurringTaskInfo) {
277
+ newTask.parentRecurringTaskInfo = {
278
+ ...oldTask.parentRecurringTaskInfo,
279
+ taskId: getUUID(oldTask.parentRecurringTaskInfo.taskId)
280
+ };
281
+ }
282
+
283
+ verifyDoc(oldTask, newTask);
284
+ newTasksToCreate.push(newTask);
148
285
  }
149
286
 
150
- newTasks.push(newTask);
151
- oldTaskIds.push(task._id);
287
+ const children = taskChildrenMap.get(oldTask._id.toString());
288
+ if (children) {
289
+ queue.push(...children);
290
+ }
152
291
  }
153
- }
154
-
155
- // --- Process UserConfigs ---
156
- for (const config of configs) {
157
- if (config._id instanceof ObjectId) {
158
- const newId = getNewId(config._id);
159
- if (!newId) continue;
160
-
161
- const newConfig = { ...config, _id: newId };
162
-
163
- // Fix userId
164
- if (newConfig.userId) newConfig.userId = getNewId(newConfig.userId) || newConfig.userId;
165
292
 
166
- // Fix collaborators
167
- if (Array.isArray(newConfig.collaborators)) {
168
- newConfig.collaborators = newConfig.collaborators.map((id: any) => getNewId(id) || id);
293
+ // 3. Create new Configs
294
+ const userConfigs = configs.filter((c) => c.userId.toString() === oldUserIdStr);
295
+ userConfigs.forEach((oldConfig) => {
296
+ const newConfig = createNewDoc(oldConfig);
297
+ if (!newConfig) return;
298
+ newConfig.userId = newUserId;
299
+ newConfig.collaborators = (oldConfig.collaborators || []).map((id) =>
300
+ getUUID(id)
301
+ );
302
+ if (newConfig.taskListSortSettings) {
303
+ Object.entries(newConfig.taskListSortSettings).forEach(
304
+ ([category, settings]: [string, any]) => {
305
+ const newSettings = {
306
+ userId: getUUID(settings.userId),
307
+ sortList: settings.sortList
308
+ };
309
+ newConfig.taskListSortSettings[category] = newSettings;
310
+ }
311
+ );
169
312
  }
313
+ if (newConfig.taskListFilterSettings) {
314
+ Object.entries(newConfig.taskListFilterSettings).forEach(
315
+ ([category, settings]: [string, any]) => {
316
+ const newSettings = {
317
+ ...settings,
318
+ userId: getUUID(settings.userId)
319
+ };
320
+ newConfig.taskListFilterSettings[category] = newSettings;
321
+ }
322
+ );
323
+ }
324
+ verifyDoc(oldConfig, newConfig);
325
+ newConfigsToCreate.push(newConfig);
326
+ });
170
327
 
171
- newConfigs.push(newConfig);
172
- oldConfigIds.push(config._id);
173
- }
174
- }
328
+ // 4. Nonogram Items
329
+ const userNonogramItems = nonogramItems.filter((i) => i.userId.toString() === oldUserIdStr);
330
+ userNonogramItems.forEach((oldItem) => {
331
+ const newItem = createNewDoc(oldItem);
332
+ if (!newItem) return;
333
+ newItem.userId = newUserId;
334
+ verifyDoc(oldItem, newItem);
335
+ newNonogramItemsToCreate.push(newItem);
336
+ });
175
337
 
176
- // 5. Execute
177
- if (dryRun) {
178
- DR.logger.info(`[DRY RUN] Would insert ${newUsers.length} users and delete ${oldUserIds.length} old ones.`);
179
- DR.logger.info(`[DRY RUN] Would insert ${newTasks.length} tasks and delete ${oldTaskIds.length} old ones.`);
180
- DR.logger.info(`[DRY RUN] Would insert ${newConfigs.length} configs and delete ${oldConfigIds.length} old ones.`);
181
- return;
338
+ // 5. Nonogram Upgrades
339
+ const userNonogramUpgrades = nonogramUpgrades.filter((u) => u.userId.toString() === oldUserIdStr);
340
+ userNonogramUpgrades.forEach((oldUpgrade) => {
341
+ const newUpgrade = createNewDoc(oldUpgrade);
342
+ if (!newUpgrade) return;
343
+ newUpgrade.userId = newUserId;
344
+ verifyDoc(oldUpgrade, newUpgrade);
345
+ newNonogramUpgradesToCreate.push(newUpgrade);
346
+ });
182
347
  }
183
348
 
184
- DR.logger.info('Executing migration...');
185
-
186
- // Users
187
- if (newUsers.length > 0) {
188
- await userRepo.insertMany(newUsers);
189
- await userRepo.deleteList(oldUserIds);
190
- DR.logger.success(`Migrated ${newUsers.length} users.`);
349
+ // Now create related documents for each user
350
+ legacyUsers.forEach((u) => createNewDocsForUser(u));
351
+
352
+ const legacyUserIds = new Set(legacyUsers.map((u) => u._id.toString()));
353
+ const expectedUsers = legacyUsers.length;
354
+ const expectedApiKeys = apiKeys.filter((k) =>
355
+ legacyUserIds.has(k.userId.toString())
356
+ ).length;
357
+ const expectedTasks = tasks.filter((t) =>
358
+ legacyUserIds.has(t.userId.toString())
359
+ ).length;
360
+ const expectedConfigs = configs.filter((c) =>
361
+ legacyUserIds.has(c.userId.toString())
362
+ ).length;
363
+ const expectedNonogramItems = nonogramItems.filter((i) =>
364
+ legacyUserIds.has(i.userId.toString())
365
+ ).length;
366
+ const expectedNonogramUpgrades = nonogramUpgrades.filter((u) =>
367
+ legacyUserIds.has(u.userId.toString())
368
+ ).length;
369
+
370
+ if (newUsersToCreate.length !== expectedUsers) {
371
+ DR.logger.error(
372
+ `Expected ${expectedUsers} users, but prepped ${newUsersToCreate.length}.`
373
+ );
191
374
  }
192
-
193
- // Tasks
194
- if (newTasks.length > 0) {
195
- await taskRepo.insertMany(newTasks);
196
- await taskRepo.deleteList(oldTaskIds);
197
- DR.logger.success(`Migrated ${newTasks.length} tasks.`);
375
+ if (newApiKeysToCreate.length !== expectedApiKeys) {
376
+ DR.logger.error(
377
+ `Expected ${expectedApiKeys} API keys, but prepped ${newApiKeysToCreate.length}.`
378
+ );
379
+ }
380
+ if (newTasksToCreate.length !== expectedTasks) {
381
+ DR.logger.error(
382
+ `Expected ${expectedTasks} tasks, but prepped ${newTasksToCreate.length}.`
383
+ );
384
+ }
385
+ if (newConfigsToCreate.length !== expectedConfigs) {
386
+ DR.logger.error(
387
+ `Expected ${expectedConfigs} configs, but prepped ${newConfigsToCreate.length}.`
388
+ );
389
+ }
390
+ if (newNonogramItemsToCreate.length !== expectedNonogramItems) {
391
+ DR.logger.error(
392
+ `Expected ${expectedNonogramItems} nonogram items, but prepped ${newNonogramItemsToCreate.length}.`
393
+ );
394
+ }
395
+ if (newNonogramUpgradesToCreate.length !== expectedNonogramUpgrades) {
396
+ DR.logger.error(
397
+ `Expected ${expectedNonogramUpgrades} nonogram upgrades, but prepped ${newNonogramUpgradesToCreate.length}.`
398
+ );
198
399
  }
199
400
 
200
- // Configs
201
- if (newConfigs.length > 0) {
202
- await configRepo.insertMany(newConfigs);
203
- await configRepo.deleteList(oldConfigIds);
204
- DR.logger.success(`Migrated ${newConfigs.length} configs.`);
401
+ DR.logger.info(`Prepped ${newUsersToCreate.length} new users.`);
402
+ DR.logger.info(`Prepped ${newApiKeysToCreate.length} new API keys.`);
403
+ DR.logger.info(`Prepped ${newTasksToCreate.length} new tasks.`);
404
+ DR.logger.info(`Prepped ${newConfigsToCreate.length} new configs.`);
405
+ DR.logger.info(
406
+ `Prepped ${newNonogramItemsToCreate.length} new nonogram items.`
407
+ );
408
+ DR.logger.info(
409
+ `Prepped ${newNonogramUpgradesToCreate.length} new nonogram upgrades.`
410
+ );
411
+ DR.logger.info(`In total, prepped ${
412
+ newUsersToCreate.length +
413
+ newApiKeysToCreate.length +
414
+ newTasksToCreate.length +
415
+ newConfigsToCreate.length +
416
+ newNonogramItemsToCreate.length +
417
+ newNonogramUpgradesToCreate.length
418
+ } documents for insertion.`);
419
+
420
+ if (!dryRun) {
421
+ DR.logger.info('Dry run is false. Inserting documents into DB...');
422
+ if (newUsersToCreate.length > 0) {
423
+ await (await userRepo.getCollection()).insertMany(newUsersToCreate);
424
+ }
425
+ if (newApiKeysToCreate.length > 0) {
426
+ await (await apiKeyRepo.getCollection()).insertMany(newApiKeysToCreate);
427
+ }
428
+ if (newTasksToCreate.length > 0) {
429
+ await (await taskRepo.getCollection()).insertMany(newTasksToCreate);
430
+ }
431
+ if (newConfigsToCreate.length > 0) {
432
+ await (await configRepo.getCollection()).insertMany(newConfigsToCreate);
433
+ }
434
+ if (newNonogramItemsToCreate.length > 0) {
435
+ await (
436
+ await nonogramItemRepo.getCollection()
437
+ ).insertMany(newNonogramItemsToCreate);
438
+ }
439
+ if (newNonogramUpgradesToCreate.length > 0) {
440
+ await (
441
+ await nonogramUpgradesRepo.getCollection()
442
+ ).insertMany(newNonogramUpgradesToCreate);
443
+ }
444
+ DR.logger.info('Insertion complete.');
445
+ } else {
446
+ DR.logger.info('Dry run is true. Skipping DB insertion.');
205
447
  }
206
448
 
207
- DR.logger.success('Migration complete!');
449
+ return;
208
450
  }
451
+
452
+ // We started with 1204 docs
209
453
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@aneuhold/be-ts-db-lib",
3
3
  "author": "Anton G. Neuhold Jr.",
4
4
  "license": "MIT",
5
- "version": "3.0.0",
5
+ "version": "3.0.2",
6
6
  "description": "A backend database library meant to actually interact with various databases in personal projects",
7
7
  "packageManager": "pnpm@10.12.1",
8
8
  "type": "module",
@@ -57,14 +57,15 @@
57
57
  "MongoDB"
58
58
  ],
59
59
  "dependencies": {
60
- "@aneuhold/be-ts-lib": "^3.0.0",
61
- "@aneuhold/core-ts-db-lib": "^3.0.0",
60
+ "@aneuhold/be-ts-lib": "^3.0.1",
61
+ "@aneuhold/core-ts-db-lib": "^3.0.1",
62
62
  "@aneuhold/core-ts-lib": "^2.3.11",
63
63
  "bson": "^7.0.0",
64
- "mongodb": "^7.0.0"
64
+ "mongodb": "^7.0.0",
65
+ "uuid": "^13.0.0"
65
66
  },
66
67
  "devDependencies": {
67
- "@aneuhold/local-npm-registry": "^0.2.17",
68
+ "@aneuhold/local-npm-registry": "^0.2.18",
68
69
  "@aneuhold/main-scripts": "^2.7.2",
69
70
  "@types/node": "^24.10.0",
70
71
  "@types/node-fetch": "^2.6.13",