appwrite-utils-cli 0.9.53 → 0.9.55

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 CHANGED
@@ -124,6 +124,8 @@ This updated CLI ensures that developers have robust tools at their fingertips t
124
124
 
125
125
  ## Changelog
126
126
 
127
+ - 0.9.55: Updated to use `node-appwrite@14` for appwrite 1.6.0
128
+ - 0.9.54: Added small delay (`100ms`) between collection deletions, reduced other delays from `1000` to `500/250ms`
127
129
  - 0.9.53: Reduced delay, went too far
128
130
  - 0.9.52: Add delay after creating indexes, attributes, and others to prevent `fetch failed` errors during large-scale collection creation
129
131
  - 0.9.51: Fix transfer databases, remove "ensure duplicates" check
@@ -11,61 +11,48 @@ const attributesSame = (databaseAttribute, configAttribute) => {
11
11
  export const createOrUpdateAttribute = async (db, dbId, collection, attribute) => {
12
12
  let action = "create";
13
13
  let foundAttribute;
14
- const updateEnabled = false;
15
14
  let finalAttribute = attribute;
16
15
  try {
17
16
  const collectionAttr = collection.attributes.find(
18
- // @ts-expect-error
17
+ // @ts-ignore
19
18
  (attr) => attr.key === attribute.key);
20
19
  foundAttribute = parseAttribute(collectionAttr);
21
20
  }
22
21
  catch (error) {
23
22
  foundAttribute = undefined;
24
23
  }
25
- if (foundAttribute &&
26
- attributesSame(foundAttribute, attribute) &&
27
- updateEnabled) {
28
- // Check if mutable properties have changed and set action to "update" if necessary
24
+ if (foundAttribute) {
25
+ // Check if any properties have changed
29
26
  const requiredChanged = "required" in foundAttribute && "required" in attribute
30
27
  ? foundAttribute.required !== attribute.required
31
28
  : false;
32
- // const xdefaultChanged =
33
- // "xdefault" in foundAttribute && "xdefault" in attribute
34
- // ? foundAttribute.xdefault !== attribute.xdefault
35
- // : false;
29
+ const xdefaultChanged = "xdefault" in foundAttribute && "xdefault" in attribute
30
+ ? foundAttribute.xdefault !== attribute.xdefault
31
+ : false;
36
32
  const onDeleteChanged = foundAttribute.type === "relationship" &&
37
33
  attribute.type === "relationship" &&
38
34
  "onDelete" in foundAttribute &&
39
35
  "onDelete" in attribute
40
36
  ? foundAttribute.onDelete !== attribute.onDelete
41
37
  : false;
42
- if (requiredChanged || onDeleteChanged) {
43
- console.log(`Required changed: ${requiredChanged}\nOnDelete changed: ${onDeleteChanged}`);
38
+ if (requiredChanged ||
39
+ xdefaultChanged ||
40
+ onDeleteChanged ||
41
+ !attributesSame(foundAttribute, attribute)) {
42
+ console.log(`Updating attribute: ${attribute.key}\nRequired changed: ${requiredChanged}\nDefault changed: ${xdefaultChanged}\nOnDelete changed: ${onDeleteChanged}`);
44
43
  console.log(`Found attribute: ${JSON.stringify(foundAttribute, null, 2)}`);
45
- console.log(`Attribute: ${JSON.stringify(attribute, null, 2)}`);
44
+ console.log(`New attribute: ${JSON.stringify(attribute, null, 2)}`);
46
45
  finalAttribute = {
47
- ...attribute,
48
46
  ...foundAttribute,
47
+ ...attribute,
49
48
  };
50
49
  action = "update";
51
50
  }
52
51
  else {
53
- // If no properties that can be updated have changed, return early
52
+ // If no properties have changed, return early
54
53
  return;
55
54
  }
56
55
  }
57
- else if (foundAttribute &&
58
- !attributesSame(foundAttribute, attribute) &&
59
- updateEnabled) {
60
- console.log(`Deleting attribute with same key ${attribute.key} -- but different values -- ${JSON.stringify(attribute, null, 2)} -- ${JSON.stringify(foundAttribute, null, 2)}`);
61
- await db.deleteAttribute(dbId, collection.$id, attribute.key);
62
- // After deletion, you might want to create the attribute anew
63
- finalAttribute = attribute;
64
- action = "create";
65
- }
66
- else if (!updateEnabled && foundAttribute) {
67
- return;
68
- }
69
56
  // Relationship attribute logic with adjustments
70
57
  let collectionFoundViaRelatedCollection;
71
58
  let relatedCollectionId;
@@ -8,10 +8,10 @@ export const createOrUpdateIndex = async (dbId, db, collectionId, index) => {
8
8
  let createIndex = false;
9
9
  let newIndex = null;
10
10
  if (existingIndex.total > 0 &&
11
- existingIndex.indexes.some((index) => (index.key === index.key &&
12
- index.type === index.type &&
13
- index.attributes === index.attributes) ||
14
- JSON.stringify(index) === JSON.stringify(index))) {
11
+ !existingIndex.indexes.some((existingIndex) => (existingIndex.key === index.key &&
12
+ existingIndex.type === index.type &&
13
+ existingIndex.attributes === index.attributes) ||
14
+ JSON.stringify(existingIndex) === JSON.stringify(index))) {
15
15
  await db.deleteIndex(dbId, collectionId, existingIndex.indexes[0].key);
16
16
  createIndex = true;
17
17
  }
@@ -24,6 +24,6 @@ export const createOrUpdateIndexes = async (dbId, db, collectionId, indexes) =>
24
24
  for (const index of indexes) {
25
25
  await tryAwaitWithRetry(async () => await createOrUpdateIndex(dbId, db, collectionId, index));
26
26
  // Add delay after each index creation/update
27
- await delay(1000);
27
+ await delay(500);
28
28
  }
29
29
  };
@@ -97,6 +97,7 @@ export const wipeDatabase = async (database, databaseId) => {
97
97
  collectionName: name,
98
98
  });
99
99
  tryAwaitWithRetry(async () => await database.deleteCollection(databaseId, collectionId)); // Try to delete the collection and ignore errors if it doesn't exist or if it's already being deleted
100
+ await delay(100);
100
101
  }
101
102
  return collectionsDeleted;
102
103
  };
@@ -174,16 +175,16 @@ export const createOrUpdateCollections = async (database, databaseId, config, de
174
175
  await tryAwaitWithRetry(async () => await database.updateCollection(databaseId, collectionToUse.$id, collection.name, permissions, collection.documentSecurity ?? false, collection.enabled ?? true));
175
176
  }
176
177
  // Add delay after creating/updating collection
177
- await delay(1000);
178
+ await delay(250);
178
179
  // Update attributes and indexes for the collection
179
180
  console.log("Creating Attributes");
180
181
  await createUpdateCollectionAttributes(database, databaseId, collectionToUse, attributes);
181
182
  // Add delay after creating attributes
182
- await delay(1000);
183
+ await delay(250);
183
184
  console.log("Creating Indexes");
184
185
  await createOrUpdateIndexes(databaseId, database, collectionToUse.$id, indexes ?? []);
185
186
  // Add delay after creating indexes
186
- await delay(1000);
187
+ await delay(250);
187
188
  }
188
189
  // Process any remaining tasks in the queue
189
190
  await processQueue(database, databaseId);
@@ -1,7 +1,7 @@
1
1
  import { Databases, Query } from "node-appwrite";
2
2
  import { createOrUpdateAttribute } from "./attributes.js";
3
3
  import { getMigrationCollectionSchemas } from "./backup.js";
4
- import { areCollectionNamesSame, toCamelCase, tryAwaitWithRetry, } from "../utils/index.js";
4
+ import { areCollectionNamesSame, delay, toCamelCase, tryAwaitWithRetry, } from "../utils/index.js";
5
5
  import {} from "appwrite-utils";
6
6
  import { ulid } from "ulidx";
7
7
  export const setupMigrationDatabase = async (config) => {
@@ -48,6 +48,7 @@ export const setupMigrationDatabase = async (config) => {
48
48
  for (const attribute of attributes) {
49
49
  try {
50
50
  await createOrUpdateAttribute(database, db.$id, collectionFound, attribute);
51
+ await delay(100);
51
52
  console.log(`Attribute created/updated: ${attribute.key}`);
52
53
  }
53
54
  catch (attrError) {
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.9.53",
4
+ "version": "0.9.55",
5
5
  "main": "src/main.ts",
6
6
  "type": "module",
7
7
  "repository": {
@@ -38,7 +38,7 @@
38
38
  "lodash": "^4.17.21",
39
39
  "luxon": "^3.5.0",
40
40
  "nanostores": "^0.10.3",
41
- "node-appwrite": "^13.0.0",
41
+ "node-appwrite": "^14.1.0",
42
42
  "tsx": "^4.17.0",
43
43
  "ulidx": "^2.4.0",
44
44
  "winston": "^3.14.2",
@@ -27,11 +27,10 @@ export const createOrUpdateAttribute = async (
27
27
  ): Promise<void> => {
28
28
  let action = "create";
29
29
  let foundAttribute: Attribute | undefined;
30
- const updateEnabled = false;
31
30
  let finalAttribute: any = attribute;
32
31
  try {
33
32
  const collectionAttr = collection.attributes.find(
34
- // @ts-expect-error
33
+ // @ts-ignore
35
34
  (attr) => attr.key === attribute.key
36
35
  ) as unknown as any;
37
36
  foundAttribute = parseAttribute(collectionAttr);
@@ -39,21 +38,17 @@ export const createOrUpdateAttribute = async (
39
38
  foundAttribute = undefined;
40
39
  }
41
40
 
42
- if (
43
- foundAttribute &&
44
- attributesSame(foundAttribute, attribute) &&
45
- updateEnabled
46
- ) {
47
- // Check if mutable properties have changed and set action to "update" if necessary
41
+ if (foundAttribute) {
42
+ // Check if any properties have changed
48
43
  const requiredChanged =
49
44
  "required" in foundAttribute && "required" in attribute
50
45
  ? foundAttribute.required !== attribute.required
51
46
  : false;
52
47
 
53
- // const xdefaultChanged =
54
- // "xdefault" in foundAttribute && "xdefault" in attribute
55
- // ? foundAttribute.xdefault !== attribute.xdefault
56
- // : false;
48
+ const xdefaultChanged =
49
+ "xdefault" in foundAttribute && "xdefault" in attribute
50
+ ? foundAttribute.xdefault !== attribute.xdefault
51
+ : false;
57
52
 
58
53
  const onDeleteChanged =
59
54
  foundAttribute.type === "relationship" &&
@@ -63,43 +58,28 @@ export const createOrUpdateAttribute = async (
63
58
  ? foundAttribute.onDelete !== attribute.onDelete
64
59
  : false;
65
60
 
66
- if (requiredChanged || onDeleteChanged) {
61
+ if (
62
+ requiredChanged ||
63
+ xdefaultChanged ||
64
+ onDeleteChanged ||
65
+ !attributesSame(foundAttribute, attribute)
66
+ ) {
67
67
  console.log(
68
- `Required changed: ${requiredChanged}\nOnDelete changed: ${onDeleteChanged}`
68
+ `Updating attribute: ${attribute.key}\nRequired changed: ${requiredChanged}\nDefault changed: ${xdefaultChanged}\nOnDelete changed: ${onDeleteChanged}`
69
69
  );
70
70
  console.log(
71
71
  `Found attribute: ${JSON.stringify(foundAttribute, null, 2)}`
72
72
  );
73
- console.log(`Attribute: ${JSON.stringify(attribute, null, 2)}`);
73
+ console.log(`New attribute: ${JSON.stringify(attribute, null, 2)}`);
74
74
  finalAttribute = {
75
- ...attribute,
76
75
  ...foundAttribute,
76
+ ...attribute,
77
77
  };
78
78
  action = "update";
79
79
  } else {
80
- // If no properties that can be updated have changed, return early
80
+ // If no properties have changed, return early
81
81
  return;
82
82
  }
83
- } else if (
84
- foundAttribute &&
85
- !attributesSame(foundAttribute, attribute) &&
86
- updateEnabled
87
- ) {
88
- console.log(
89
- `Deleting attribute with same key ${
90
- attribute.key
91
- } -- but different values -- ${JSON.stringify(
92
- attribute,
93
- null,
94
- 2
95
- )} -- ${JSON.stringify(foundAttribute, null, 2)}`
96
- );
97
- await db.deleteAttribute(dbId, collection.$id, attribute.key);
98
- // After deletion, you might want to create the attribute anew
99
- finalAttribute = attribute;
100
- action = "create";
101
- } else if (!updateEnabled && foundAttribute) {
102
- return;
103
83
  }
104
84
 
105
85
  // Relationship attribute logic with adjustments
@@ -15,12 +15,12 @@ export const createOrUpdateIndex = async (
15
15
  let newIndex: Models.Index | null = null;
16
16
  if (
17
17
  existingIndex.total > 0 &&
18
- existingIndex.indexes.some(
19
- (index) =>
20
- (index.key === index.key &&
21
- index.type === index.type &&
22
- index.attributes === index.attributes) ||
23
- JSON.stringify(index) === JSON.stringify(index)
18
+ !existingIndex.indexes.some(
19
+ (existingIndex) =>
20
+ (existingIndex.key === index.key &&
21
+ existingIndex.type === index.type &&
22
+ existingIndex.attributes === index.attributes) ||
23
+ JSON.stringify(existingIndex) === JSON.stringify(index)
24
24
  )
25
25
  ) {
26
26
  await db.deleteIndex(dbId, collectionId, existingIndex.indexes[0].key);
@@ -50,6 +50,6 @@ export const createOrUpdateIndexes = async (
50
50
  async () => await createOrUpdateIndex(dbId, db, collectionId, index)
51
51
  );
52
52
  // Add delay after each index creation/update
53
- await delay(1000);
53
+ await delay(500);
54
54
  }
55
55
  };
@@ -141,6 +141,7 @@ export const wipeDatabase = async (
141
141
  tryAwaitWithRetry(
142
142
  async () => await database.deleteCollection(databaseId, collectionId)
143
143
  ); // Try to delete the collection and ignore errors if it doesn't exist or if it's already being deleted
144
+ await delay(100);
144
145
  }
145
146
  return collectionsDeleted;
146
147
  };
@@ -261,7 +262,7 @@ export const createOrUpdateCollections = async (
261
262
  }
262
263
 
263
264
  // Add delay after creating/updating collection
264
- await delay(1000);
265
+ await delay(250);
265
266
 
266
267
  // Update attributes and indexes for the collection
267
268
  console.log("Creating Attributes");
@@ -273,7 +274,7 @@ export const createOrUpdateCollections = async (
273
274
  );
274
275
 
275
276
  // Add delay after creating attributes
276
- await delay(1000);
277
+ await delay(250);
277
278
 
278
279
  console.log("Creating Indexes");
279
280
  await createOrUpdateIndexes(
@@ -284,7 +285,7 @@ export const createOrUpdateCollections = async (
284
285
  );
285
286
 
286
287
  // Add delay after creating indexes
287
- await delay(1000);
288
+ await delay(250);
288
289
  }
289
290
  // Process any remaining tasks in the queue
290
291
  await processQueue(database, databaseId);
@@ -3,6 +3,7 @@ import { createOrUpdateAttribute } from "./attributes.js";
3
3
  import { getMigrationCollectionSchemas } from "./backup.js";
4
4
  import {
5
5
  areCollectionNamesSame,
6
+ delay,
6
7
  toCamelCase,
7
8
  tryAwaitWithRetry,
8
9
  } from "../utils/index.js";
@@ -87,6 +88,7 @@ export const setupMigrationDatabase = async (config: AppwriteConfig) => {
87
88
  collectionFound,
88
89
  attribute
89
90
  );
91
+ await delay(100);
90
92
  console.log(`Attribute created/updated: ${attribute.key}`);
91
93
  } catch (attrError) {
92
94
  console.error(