appwrite-utils-cli 0.0.251 → 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.
@@ -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
- for (const data of currentData.data) {
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
- Object.assign(currentUserData.data[i].finalData, transformedItem);
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
- logger.error(`No old ID found (to update another document with) in prepareUpdateData for ${collection.name}, ${JSON.stringify(item, null, 2)}`);
717
- continue;
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.251",
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
- for (const data of currentData.data) {
680
- if (
681
- data.finalData.docId === oldId ||
682
- data.finalData.userId === oldId
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
- Object.assign(currentUserData.data[i].finalData, transformedItem);
703
- Object.assign(currentUserData.data[i].rawData, item);
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
- currentData.data[i].finalData = {
727
- ...currentData.data[i].finalData,
728
- ...transformedItem,
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
- logger.error(
945
- `No old ID found (to update another document with) in prepareUpdateData for ${
946
- collection.name
947
- }, ${JSON.stringify(item, null, 2)}`
965
+ const currentCollectionData = this.importMap.get(
966
+ this.getCollectionKey(collection.name)
948
967
  );
949
- continue;
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) {