appwrite-utils-cli 0.0.63 → 0.0.65

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.
@@ -623,6 +623,16 @@ export declare const CollectionImportDataSchema: z.ZodObject<{
623
623
  relatedCollection: string;
624
624
  relationType: "oneToMany" | "manyToOne" | "oneToOne" | "manyToMany";
625
625
  twoWay: boolean;
626
+ /**
627
+ * Generates attribute mappings with post-import actions based on the provided attribute mappings.
628
+ * This method checks each mapping for a fileData attribute and adds a post-import action to create a file
629
+ * and update the field with the file's ID if necessary.
630
+ *
631
+ * @param attributeMappings - The attribute mappings from the import definition.
632
+ * @param context - The context object containing information about the database, collection, and document.
633
+ * @param item - The item being imported, used for resolving template paths in fileData mappings.
634
+ * @returns The attribute mappings updated with any necessary post-import actions.
635
+ */
626
636
  twoWayKey: string;
627
637
  onDelete: "setNull" | "cascade" | "restrict";
628
638
  side: "parent" | "child";
@@ -1235,6 +1245,16 @@ export declare const CollectionImportDataSchema: z.ZodObject<{
1235
1245
  relatedCollection: string;
1236
1246
  relationType: "oneToMany" | "manyToOne" | "oneToOne" | "manyToMany";
1237
1247
  twoWay: boolean;
1248
+ /**
1249
+ * Generates attribute mappings with post-import actions based on the provided attribute mappings.
1250
+ * This method checks each mapping for a fileData attribute and adds a post-import action to create a file
1251
+ * and update the field with the file's ID if necessary.
1252
+ *
1253
+ * @param attributeMappings - The attribute mappings from the import definition.
1254
+ * @param context - The context object containing information about the database, collection, and document.
1255
+ * @param item - The item being imported, used for resolving template paths in fileData mappings.
1256
+ * @returns The attribute mappings updated with any necessary post-import actions.
1257
+ */
1238
1258
  twoWayKey: string;
1239
1259
  onDelete: "setNull" | "cascade" | "restrict";
1240
1260
  side: "parent" | "child";
@@ -1635,6 +1655,16 @@ export declare class DataLoader {
1635
1655
  relatedCollection: string;
1636
1656
  relationType: "oneToMany" | "manyToOne" | "oneToOne" | "manyToMany";
1637
1657
  twoWay: boolean;
1658
+ /**
1659
+ * Generates attribute mappings with post-import actions based on the provided attribute mappings.
1660
+ * This method checks each mapping for a fileData attribute and adds a post-import action to create a file
1661
+ * and update the field with the file's ID if necessary.
1662
+ *
1663
+ * @param attributeMappings - The attribute mappings from the import definition.
1664
+ * @param context - The context object containing information about the database, collection, and document.
1665
+ * @param item - The item being imported, used for resolving template paths in fileData mappings.
1666
+ * @returns The attribute mappings updated with any necessary post-import actions.
1667
+ */
1638
1668
  twoWayKey: string;
1639
1669
  onDelete: "setNull" | "cascade" | "restrict";
1640
1670
  side: "parent" | "child";
@@ -278,6 +278,11 @@ export class DataLoader {
278
278
  userId: user.$id,
279
279
  docId: user.$id,
280
280
  },
281
+ context: {
282
+ ...user,
283
+ userId: user.$id,
284
+ docId: user.$id,
285
+ },
281
286
  rawData: user,
282
287
  });
283
288
  this.importMap.set(this.getCollectionKey("users"), importData);
@@ -449,13 +454,6 @@ export class DataLoader {
449
454
  targetValue !== undefined &&
450
455
  targetValue !== null);
451
456
  });
452
- // Log and skip if no matching data found
453
- if (!foundData.length) {
454
- console.log(`No data found for collection ${collectionConfig.name}:\nTarget collection: ${targetCollectionKey}\nValue to match: ${valueToMatch}\nField to set: ${fieldToSetKey}\nTarget field to match: ${targetFieldKey}\nTarget field value: ${idMapping.targetField}`);
455
- logger.info(`No data found for collection: ${targetCollectionKey} with value: ${valueToMatch} for field: ${fieldToSetKey} -- idMapping: ${JSON.stringify(idMapping, null, 2)}`);
456
- continue;
457
- }
458
- needsUpdate = true;
459
457
  const getCurrentDataFiltered = (currentData) => {
460
458
  if (Array.isArray(currentData.finalData[fieldToSetKey])) {
461
459
  return currentData.finalData[fieldToSetKey].filter((data) => `${data}` !== `${valueToMatch}`);
@@ -464,6 +462,13 @@ export class DataLoader {
464
462
  };
465
463
  // Get the current data to be updated
466
464
  const currentDataFiltered = getCurrentDataFiltered(collectionData.data[i]);
465
+ // Log and skip if no matching data found
466
+ if (!foundData.length) {
467
+ console.log(`No data found for collection ${collectionConfig.name}:\nTarget collection: ${targetCollectionKey}\nValue to match: ${valueToMatch}\nField to set: ${fieldToSetKey}\nTarget field to match: ${targetFieldKey}\nTarget field value: ${idMapping.targetField}`);
468
+ logger.info(`No data found for collection: ${targetCollectionKey} with value: ${valueToMatch} for field: ${fieldToSetKey} -- idMapping: ${JSON.stringify(idMapping, null, 2)}`);
469
+ continue;
470
+ }
471
+ needsUpdate = true;
467
472
  // Extract the new data to set
468
473
  const newData = foundData.map((data) => {
469
474
  const valueFound = this.getValueFromData(data.finalData, data.context, idMapping.targetField);
@@ -576,6 +581,11 @@ export class DataLoader {
576
581
  * @returns The transformed item with user-specific keys removed.
577
582
  */
578
583
  prepareUserData(item, attributeMappings, primaryKeyField, newId) {
584
+ if (this.userExistsMap.has(newId) ||
585
+ Array.from(this.emailToUserIdMap.values()).includes(newId) ||
586
+ Array.from(this.phoneToUserIdMap.values()).includes(newId)) {
587
+ newId = this.getTrueUniqueId(this.getCollectionKey("users"));
588
+ }
579
589
  let transformedItem = this.transformData(item, attributeMappings);
580
590
  const userData = AuthUserCreateSchema.safeParse(transformedItem);
581
591
  if (!userData.success || !(userData.data.email && userData.data.phone)) {
@@ -808,7 +818,18 @@ export class DataLoader {
808
818
  updatedData.data[i].context.userId === existingId) {
809
819
  updatedData.data[i].finalData = this.mergeObjects(updatedData.data[i].finalData, transformedItem);
810
820
  updatedData.data[i].context = this.mergeObjects(updatedData.data[i].context, context);
811
- updatedData.data[i].importDef = this.mergeObjects(updatedData.data[i].importDef, newImportDef);
821
+ const mergedImportDef = {
822
+ ...updatedData.data[i].importDef,
823
+ idMappings: [
824
+ ...(updatedData.data[i].importDef?.idMappings || []),
825
+ ...(newImportDef.idMappings || []),
826
+ ],
827
+ attributeMappings: [
828
+ ...(updatedData.data[i].importDef?.attributeMappings || []),
829
+ ...(newImportDef.attributeMappings || []),
830
+ ],
831
+ };
832
+ updatedData.data[i].importDef = mergedImportDef;
812
833
  this.importMap.set(this.getCollectionKey(collection.name), updatedData);
813
834
  this.oldIdToNewIdPerCollectionMap.set(this.getCollectionKey(collection.name), collectionOldIdToNewIdMap);
814
835
  foundData = true;
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.63",
4
+ "version": "0.0.65",
5
5
  "main": "src/main.ts",
6
6
  "type": "module",
7
7
  "repository": {
@@ -33,7 +33,7 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@types/inquirer": "^9.0.7",
36
- "appwrite-utils": "^0.3.1",
36
+ "appwrite-utils": "^0.3.2",
37
37
  "commander": "^12.0.0",
38
38
  "inquirer": "^9.2.20",
39
39
  "js-yaml": "^4.1.0",
@@ -348,6 +348,11 @@ export class DataLoader {
348
348
  userId: user.$id,
349
349
  docId: user.$id,
350
350
  },
351
+ context: {
352
+ ...user,
353
+ userId: user.$id,
354
+ docId: user.$id,
355
+ },
351
356
  rawData: user,
352
357
  });
353
358
  this.importMap.set(this.getCollectionKey("users"), importData);
@@ -571,6 +576,20 @@ export class DataLoader {
571
576
  );
572
577
  }
573
578
  );
579
+
580
+ const getCurrentDataFiltered = (currentData: any) => {
581
+ if (Array.isArray(currentData.finalData[fieldToSetKey])) {
582
+ return currentData.finalData[fieldToSetKey].filter(
583
+ (data: any) => `${data}` !== `${valueToMatch}`
584
+ );
585
+ }
586
+ return currentData.finalData[fieldToSetKey];
587
+ };
588
+
589
+ // Get the current data to be updated
590
+ const currentDataFiltered = getCurrentDataFiltered(
591
+ collectionData.data[i]
592
+ );
574
593
  // Log and skip if no matching data found
575
594
  if (!foundData.length) {
576
595
  console.log(
@@ -588,20 +607,6 @@ export class DataLoader {
588
607
 
589
608
  needsUpdate = true;
590
609
 
591
- const getCurrentDataFiltered = (currentData: any) => {
592
- if (Array.isArray(currentData.finalData[fieldToSetKey])) {
593
- return currentData.finalData[fieldToSetKey].filter(
594
- (data: any) => `${data}` !== `${valueToMatch}`
595
- );
596
- }
597
- return currentData.finalData[fieldToSetKey];
598
- };
599
-
600
- // Get the current data to be updated
601
- const currentDataFiltered = getCurrentDataFiltered(
602
- collectionData.data[i]
603
- );
604
-
605
610
  // Extract the new data to set
606
611
  const newData = foundData.map((data) => {
607
612
  const valueFound = this.getValueFromData(
@@ -755,6 +760,13 @@ export class DataLoader {
755
760
  finalData: z.infer<typeof AuthUserCreateSchema>;
756
761
  };
757
762
  } {
763
+ if (
764
+ this.userExistsMap.has(newId) ||
765
+ Array.from(this.emailToUserIdMap.values()).includes(newId) ||
766
+ Array.from(this.phoneToUserIdMap.values()).includes(newId)
767
+ ) {
768
+ newId = this.getTrueUniqueId(this.getCollectionKey("users"));
769
+ }
758
770
  let transformedItem = this.transformData(item, attributeMappings);
759
771
  const userData = AuthUserCreateSchema.safeParse(transformedItem);
760
772
  if (!userData.success || !(userData.data.email && userData.data.phone)) {
@@ -1057,10 +1069,18 @@ export class DataLoader {
1057
1069
  updatedData.data[i].context,
1058
1070
  context
1059
1071
  );
1060
- updatedData.data[i].importDef = this.mergeObjects(
1061
- updatedData.data[i].importDef,
1062
- newImportDef
1063
- );
1072
+ const mergedImportDef = {
1073
+ ...updatedData.data[i].importDef,
1074
+ idMappings: [
1075
+ ...(updatedData.data[i].importDef?.idMappings || []),
1076
+ ...(newImportDef.idMappings || []),
1077
+ ],
1078
+ attributeMappings: [
1079
+ ...(updatedData.data[i].importDef?.attributeMappings || []),
1080
+ ...(newImportDef.attributeMappings || []),
1081
+ ],
1082
+ };
1083
+ updatedData.data[i].importDef = mergedImportDef as ImportDef;
1064
1084
  this.importMap.set(
1065
1085
  this.getCollectionKey(collection.name),
1066
1086
  updatedData