appwrite-utils-cli 0.0.250 → 0.0.252
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/migrations/dataLoader.d.ts +1 -8
- package/dist/migrations/dataLoader.js +25 -15
- package/dist/migrations/importController.js +3 -0
- package/dist/migrations/importDataActions.js +0 -1
- package/package.json +1 -1
- package/src/migrations/dataLoader.ts +44 -22
- package/src/migrations/importController.ts +2 -0
- package/src/migrations/importDataActions.ts +0 -4
@@ -4,14 +4,6 @@ import { z } from "zod";
|
|
4
4
|
import { type Databases } from "node-appwrite";
|
5
5
|
export declare const CollectionImportDataSchema: z.ZodObject<{
|
6
6
|
collection: z.ZodOptional<z.ZodObject<Omit<{
|
7
|
-
/**
|
8
|
-
* Prepares user data by checking for duplicates based on email or phone, adding to a duplicate map if found,
|
9
|
-
* and then returning the transformed item without user-specific keys.
|
10
|
-
*
|
11
|
-
* @param item - The raw item to be processed.
|
12
|
-
* @param attributeMappings - The attribute mappings for the item.
|
13
|
-
* @returns The transformed item with user-specific keys removed.
|
14
|
-
*/
|
15
7
|
$id: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
16
8
|
$createdAt: z.ZodString;
|
17
9
|
$updatedAt: z.ZodString;
|
@@ -1586,6 +1578,7 @@ export declare class DataLoader {
|
|
1586
1578
|
getAllUsers(): Promise<import("node-appwrite").Models.User<import("node-appwrite").Models.Preferences>[]>;
|
1587
1579
|
start(dbId: string): Promise<void>;
|
1588
1580
|
updateReferencesInRelatedCollections(): Promise<void>;
|
1581
|
+
updateObjectWithNonNullishValues(sourceObject: Record<string, any>, inputObject: Record<string, any>): void;
|
1589
1582
|
/**
|
1590
1583
|
* Prepares user data by checking for duplicates based on email or phone, adding to a duplicate map if found,
|
1591
1584
|
* and then returning the transformed item without user-specific keys.
|
@@ -299,6 +299,24 @@ export class DataLoader {
|
|
299
299
|
}
|
300
300
|
}
|
301
301
|
}
|
302
|
+
updateObjectWithNonNullishValues(sourceObject, inputObject) {
|
303
|
+
// Iterate through the keys of the inputObject
|
304
|
+
for (const key of Object.keys(inputObject)) {
|
305
|
+
const inputValue = inputObject[key];
|
306
|
+
const sourceValue = sourceObject[key];
|
307
|
+
// Check if the inputObject's value for the current key is non-nullish
|
308
|
+
// and either the key doesn't exist in the sourceObject or its value is nullish
|
309
|
+
if (inputValue !== null &&
|
310
|
+
inputValue !== undefined &&
|
311
|
+
inputValue !== "" &&
|
312
|
+
(sourceValue === null ||
|
313
|
+
sourceValue === undefined ||
|
314
|
+
sourceValue === "")) {
|
315
|
+
// Update the sourceObject with the inputObject's value for the current key
|
316
|
+
sourceObject[key] = inputValue;
|
317
|
+
}
|
318
|
+
}
|
319
|
+
}
|
302
320
|
// async updateReferencesInRelatedCollections() {
|
303
321
|
// // Process each collection defined in the config
|
304
322
|
// for (const collection of this.config.collections) {
|
@@ -481,7 +499,6 @@ export class DataLoader {
|
|
481
499
|
this.oldIdToNewIdPerCollectionMap
|
482
500
|
.set(this.getCollectionKey(collection.name), oldIdToNewIdMap)
|
483
501
|
.get(this.getCollectionKey(collection.name));
|
484
|
-
console.log(`${collection.name} -- collectionOldIdToNewIdMap: ${collectionOldIdToNewIdMap}`);
|
485
502
|
if (!operationId) {
|
486
503
|
throw new Error(`No import operation found for collection ${collection.name}`);
|
487
504
|
}
|
@@ -511,6 +528,7 @@ export class DataLoader {
|
|
511
528
|
// No existing user ID, generate a new unique ID
|
512
529
|
existingId = this.getTrueUniqueId(this.getCollectionKey("users"));
|
513
530
|
transformedItem.userId = existingId; // Assign the new ID to the transformed data's userId field
|
531
|
+
transformedItem.docId = existingId;
|
514
532
|
}
|
515
533
|
// Create a context object for the item, including the new ID
|
516
534
|
let context = this.createContext(db, collection, item, existingId);
|
@@ -524,12 +542,7 @@ export class DataLoader {
|
|
524
542
|
.get(this.getCollectionKey(collection.name))
|
525
543
|
?.has(`${oldId}`)) {
|
526
544
|
// Found a duplicate oldId, now decide how to merge or handle these duplicates
|
527
|
-
|
528
|
-
if (data.finalData.docId === oldId ||
|
529
|
-
data.finalData.userId === oldId) {
|
530
|
-
Object.assign(data.finalData, transformedItem);
|
531
|
-
}
|
532
|
-
}
|
545
|
+
this.updateObjectWithNonNullishValues(currentData.data[0].finalData, transformedItem);
|
533
546
|
}
|
534
547
|
else {
|
535
548
|
// No duplicate found, simply map the oldId to the new itemId
|
@@ -543,8 +556,7 @@ export class DataLoader {
|
|
543
556
|
if ((currentUserData.data[i].finalData.docId === existingId ||
|
544
557
|
currentUserData.data[i].finalData.userId === existingId) &&
|
545
558
|
!_.isEqual(currentUserData.data[i], userData)) {
|
546
|
-
|
547
|
-
Object.assign(currentUserData.data[i].rawData, item);
|
559
|
+
this.updateObjectWithNonNullishValues(currentUserData.data[i].finalData, userData.finalData);
|
548
560
|
console.log("Merging user data", currentUserData.data[i].finalData);
|
549
561
|
this.importMap.set(this.getCollectionKey("users"), currentUserData);
|
550
562
|
}
|
@@ -560,10 +572,7 @@ export class DataLoader {
|
|
560
572
|
for (let i = 0; i < currentData.data.length; i++) {
|
561
573
|
if (currentData.data[i].finalData.docId === existingId ||
|
562
574
|
currentData.data[i].finalData.userId === existingId) {
|
563
|
-
currentData.data[i].finalData
|
564
|
-
...currentData.data[i].finalData,
|
565
|
-
...transformedItem,
|
566
|
-
};
|
575
|
+
this.updateObjectWithNonNullishValues(currentData.data[i].finalData, transformedItem);
|
567
576
|
currentData.data[i].importDef = newImportDef;
|
568
577
|
this.importMap.set(this.getCollectionKey(collection.name), currentData);
|
569
578
|
this.oldIdToNewIdPerCollectionMap.set(this.getCollectionKey(collection.name), collectionOldIdToNewIdMap);
|
@@ -713,8 +722,9 @@ export class DataLoader {
|
|
713
722
|
}
|
714
723
|
}
|
715
724
|
else {
|
716
|
-
|
717
|
-
|
725
|
+
const currentCollectionData = this.importMap.get(this.getCollectionKey(collection.name));
|
726
|
+
const foundItem = currentCollectionData?.data.find((dataItem) => dataItem.rawData[importDef.primaryKeyField] === oldId);
|
727
|
+
newId = foundItem ? oldIdToNewIdMap?.get(`${oldId}`) : undefined;
|
718
728
|
}
|
719
729
|
// Log an error and continue to the next item if no new ID is found
|
720
730
|
if (!newId) {
|
@@ -103,7 +103,6 @@ export class ImportDataActions {
|
|
103
103
|
for (const mapping of attributeMap) {
|
104
104
|
const { postImportActions } = mapping;
|
105
105
|
if (!postImportActions || !Array.isArray(postImportActions)) {
|
106
|
-
console.warn(`No post-import actions defined for attribute: ${mapping.targetKey}`, postImportActions);
|
107
106
|
continue; // Skip to the next attribute if no actions are defined
|
108
107
|
}
|
109
108
|
for (const actionDef of postImportActions) {
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "appwrite-utils-cli",
|
3
3
|
"description": "Appwrite Utility Functions to help with database management, data conversion, data import, migrations, and much more. Meant to be used as a CLI tool, I do not recommend installing this in frontend environments.",
|
4
|
-
"version": "0.0.
|
4
|
+
"version": "0.0.252",
|
5
5
|
"main": "src/main.ts",
|
6
6
|
"type": "module",
|
7
7
|
"repository": {
|
@@ -389,6 +389,31 @@ export class DataLoader {
|
|
389
389
|
}
|
390
390
|
}
|
391
391
|
|
392
|
+
updateObjectWithNonNullishValues(
|
393
|
+
sourceObject: Record<string, any>,
|
394
|
+
inputObject: Record<string, any>
|
395
|
+
): void {
|
396
|
+
// Iterate through the keys of the inputObject
|
397
|
+
for (const key of Object.keys(inputObject)) {
|
398
|
+
const inputValue = inputObject[key];
|
399
|
+
const sourceValue = sourceObject[key];
|
400
|
+
|
401
|
+
// Check if the inputObject's value for the current key is non-nullish
|
402
|
+
// and either the key doesn't exist in the sourceObject or its value is nullish
|
403
|
+
if (
|
404
|
+
inputValue !== null &&
|
405
|
+
inputValue !== undefined &&
|
406
|
+
inputValue !== "" &&
|
407
|
+
(sourceValue === null ||
|
408
|
+
sourceValue === undefined ||
|
409
|
+
sourceValue === "")
|
410
|
+
) {
|
411
|
+
// Update the sourceObject with the inputObject's value for the current key
|
412
|
+
sourceObject[key] = inputValue;
|
413
|
+
}
|
414
|
+
}
|
415
|
+
}
|
416
|
+
|
392
417
|
// async updateReferencesInRelatedCollections() {
|
393
418
|
// // Process each collection defined in the config
|
394
419
|
// for (const collection of this.config.collections) {
|
@@ -605,9 +630,6 @@ export class DataLoader {
|
|
605
630
|
this.oldIdToNewIdPerCollectionMap
|
606
631
|
.set(this.getCollectionKey(collection.name), oldIdToNewIdMap)
|
607
632
|
.get(this.getCollectionKey(collection.name));
|
608
|
-
console.log(
|
609
|
-
`${collection.name} -- collectionOldIdToNewIdMap: ${collectionOldIdToNewIdMap}`
|
610
|
-
);
|
611
633
|
if (!operationId) {
|
612
634
|
throw new Error(
|
613
635
|
`No import operation found for collection ${collection.name}`
|
@@ -657,6 +679,7 @@ export class DataLoader {
|
|
657
679
|
// No existing user ID, generate a new unique ID
|
658
680
|
existingId = this.getTrueUniqueId(this.getCollectionKey("users"));
|
659
681
|
transformedItem.userId = existingId; // Assign the new ID to the transformed data's userId field
|
682
|
+
transformedItem.docId = existingId;
|
660
683
|
}
|
661
684
|
|
662
685
|
// Create a context object for the item, including the new ID
|
@@ -676,14 +699,10 @@ export class DataLoader {
|
|
676
699
|
?.has(`${oldId}`)
|
677
700
|
) {
|
678
701
|
// Found a duplicate oldId, now decide how to merge or handle these duplicates
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
) {
|
684
|
-
Object.assign(data.finalData, transformedItem);
|
685
|
-
}
|
686
|
-
}
|
702
|
+
this.updateObjectWithNonNullishValues(
|
703
|
+
currentData.data[0].finalData,
|
704
|
+
transformedItem
|
705
|
+
);
|
687
706
|
} else {
|
688
707
|
// No duplicate found, simply map the oldId to the new itemId
|
689
708
|
collectionOldIdToNewIdMap?.set(`${oldId}`, `${existingId}`);
|
@@ -699,8 +718,10 @@ export class DataLoader {
|
|
699
718
|
currentUserData.data[i].finalData.userId === existingId) &&
|
700
719
|
!_.isEqual(currentUserData.data[i], userData)
|
701
720
|
) {
|
702
|
-
|
703
|
-
|
721
|
+
this.updateObjectWithNonNullishValues(
|
722
|
+
currentUserData.data[i].finalData,
|
723
|
+
userData.finalData
|
724
|
+
);
|
704
725
|
console.log("Merging user data", currentUserData.data[i].finalData);
|
705
726
|
this.importMap.set(this.getCollectionKey("users"), currentUserData);
|
706
727
|
}
|
@@ -723,10 +744,10 @@ export class DataLoader {
|
|
723
744
|
currentData.data[i].finalData.docId === existingId ||
|
724
745
|
currentData.data[i].finalData.userId === existingId
|
725
746
|
) {
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
747
|
+
this.updateObjectWithNonNullishValues(
|
748
|
+
currentData.data[i].finalData,
|
749
|
+
transformedItem
|
750
|
+
);
|
730
751
|
currentData.data[i].importDef = newImportDef;
|
731
752
|
this.importMap.set(
|
732
753
|
this.getCollectionKey(collection.name),
|
@@ -941,12 +962,13 @@ export class DataLoader {
|
|
941
962
|
}
|
942
963
|
}
|
943
964
|
} else {
|
944
|
-
|
945
|
-
|
946
|
-
collection.name
|
947
|
-
}, ${JSON.stringify(item, null, 2)}`
|
965
|
+
const currentCollectionData = this.importMap.get(
|
966
|
+
this.getCollectionKey(collection.name)
|
948
967
|
);
|
949
|
-
|
968
|
+
const foundItem = currentCollectionData?.data.find(
|
969
|
+
(dataItem) => dataItem.rawData[importDef.primaryKeyField] === oldId
|
970
|
+
);
|
971
|
+
newId = foundItem ? oldIdToNewIdMap?.get(`${oldId}`) : undefined;
|
950
972
|
}
|
951
973
|
// Log an error and continue to the next item if no new ID is found
|
952
974
|
if (!newId) {
|
@@ -161,10 +161,6 @@ export class ImportDataActions {
|
|
161
161
|
for (const mapping of attributeMap) {
|
162
162
|
const { postImportActions } = mapping;
|
163
163
|
if (!postImportActions || !Array.isArray(postImportActions)) {
|
164
|
-
console.warn(
|
165
|
-
`No post-import actions defined for attribute: ${mapping.targetKey}`,
|
166
|
-
postImportActions
|
167
|
-
);
|
168
164
|
continue; // Skip to the next attribute if no actions are defined
|
169
165
|
}
|
170
166
|
for (const actionDef of postImportActions) {
|