appwrite-utils-cli 1.1.1 → 1.1.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.
@@ -164,16 +164,38 @@ export const createOrUpdateAttributeWithStatusCheck = async (db, dbId, collectio
164
164
  if (success) {
165
165
  return true;
166
166
  }
167
- // If not successful and we have retries left, delete collection and try again
167
+ // If not successful and we have retries left, delete specific attribute and try again
168
168
  if (retryCount < maxRetries) {
169
- console.log(chalk.yellow(`Attribute '${attribute.key}' failed/stuck, retrying...`));
170
- // Get fresh collection data
171
- const freshCollection = await db.getCollection(dbId, collection.$id);
172
- // Delete and recreate collection
173
- const newCollection = await deleteAndRecreateCollection(db, dbId, freshCollection, retryCount + 1);
174
- if (newCollection) {
175
- // Retry with the new collection
176
- return await createOrUpdateAttributeWithStatusCheck(db, dbId, newCollection, attribute, retryCount + 1, maxRetries);
169
+ console.log(chalk.yellow(`Attribute '${attribute.key}' failed/stuck, deleting and retrying...`));
170
+ // Try to delete the specific stuck attribute instead of the entire collection
171
+ try {
172
+ await db.deleteAttribute(dbId, collection.$id, attribute.key);
173
+ console.log(chalk.yellow(`Deleted stuck attribute '${attribute.key}', will retry creation`));
174
+ // Wait a bit before retry
175
+ await delay(3000);
176
+ // Get fresh collection data
177
+ const freshCollection = await db.getCollection(dbId, collection.$id);
178
+ // Retry with the same collection (attribute should be gone now)
179
+ return await createOrUpdateAttributeWithStatusCheck(db, dbId, freshCollection, attribute, retryCount + 1, maxRetries);
180
+ }
181
+ catch (deleteError) {
182
+ console.log(chalk.red(`Failed to delete stuck attribute '${attribute.key}': ${deleteError}`));
183
+ // If attribute deletion fails, only then try collection recreation as last resort
184
+ if (retryCount >= maxRetries - 1) {
185
+ console.log(chalk.yellow(`Last resort: Recreating collection for attribute '${attribute.key}'`));
186
+ // Get fresh collection data
187
+ const freshCollection = await db.getCollection(dbId, collection.$id);
188
+ // Delete and recreate collection
189
+ const newCollection = await deleteAndRecreateCollection(db, dbId, freshCollection, retryCount + 1);
190
+ if (newCollection) {
191
+ // Retry with the new collection
192
+ return await createOrUpdateAttributeWithStatusCheck(db, dbId, newCollection, attribute, retryCount + 1, maxRetries);
193
+ }
194
+ }
195
+ else {
196
+ // Continue to next retry without collection recreation
197
+ return await createOrUpdateAttributeWithStatusCheck(db, dbId, collection, attribute, retryCount + 1, maxRetries);
198
+ }
177
199
  }
178
200
  }
179
201
  console.log(chalk.red(`❌ Failed to create attribute '${attribute.key}' after ${maxRetries + 1} attempts`));
@@ -437,32 +459,58 @@ export const createUpdateCollectionAttributesWithStatusCheck = async (db, dbId,
437
459
  await delay(500); // Longer delay for deletions
438
460
  }
439
461
  }
440
- // Create attributes ONE BY ONE with proper status checking
462
+ // Create attributes ONE BY ONE with proper status checking and persistent retry logic
441
463
  console.log(chalk.blue(`Creating ${attributes.length} attributes sequentially with status monitoring...`));
442
464
  let currentCollection = collection;
443
- const failedAttributes = [];
444
- for (const attribute of attributes) {
445
- console.log(chalk.blue(`\n--- Processing attribute: ${attribute.key} ---`));
446
- const success = await createOrUpdateAttributeWithStatusCheck(db, dbId, currentCollection, attribute);
447
- if (success) {
448
- console.log(chalk.green(`✅ Successfully created attribute: ${attribute.key}`));
449
- // Get updated collection data for next iteration
465
+ let attributesToProcess = [...attributes];
466
+ let overallRetryCount = 0;
467
+ const maxOverallRetries = 3;
468
+ while (attributesToProcess.length > 0 && overallRetryCount < maxOverallRetries) {
469
+ const remainingAttributes = [...attributesToProcess];
470
+ attributesToProcess = []; // Reset for next iteration
471
+ console.log(chalk.blue(`\n=== Attempt ${overallRetryCount + 1}/${maxOverallRetries} - Processing ${remainingAttributes.length} attributes ===`));
472
+ for (const attribute of remainingAttributes) {
473
+ console.log(chalk.blue(`\n--- Processing attribute: ${attribute.key} ---`));
474
+ const success = await createOrUpdateAttributeWithStatusCheck(db, dbId, currentCollection, attribute);
475
+ if (success) {
476
+ console.log(chalk.green(`✅ Successfully created attribute: ${attribute.key}`));
477
+ // Get updated collection data for next iteration
478
+ try {
479
+ currentCollection = await db.getCollection(dbId, collection.$id);
480
+ }
481
+ catch (error) {
482
+ console.log(chalk.yellow(`Warning: Could not refresh collection data: ${error}`));
483
+ }
484
+ // Add delay between successful attributes
485
+ await delay(1000);
486
+ }
487
+ else {
488
+ console.log(chalk.red(`❌ Failed to create attribute: ${attribute.key}, will retry in next round`));
489
+ attributesToProcess.push(attribute); // Add back to retry list
490
+ }
491
+ }
492
+ if (attributesToProcess.length === 0) {
493
+ console.log(chalk.green(`\n✅ Successfully created all ${attributes.length} attributes for collection: ${collection.name}`));
494
+ return true;
495
+ }
496
+ overallRetryCount++;
497
+ if (overallRetryCount < maxOverallRetries) {
498
+ console.log(chalk.yellow(`\n⏳ Waiting 5 seconds before retrying ${attributesToProcess.length} failed attributes...`));
499
+ await delay(5000);
500
+ // Refresh collection data before retry
450
501
  try {
451
502
  currentCollection = await db.getCollection(dbId, collection.$id);
503
+ console.log(chalk.blue(`Refreshed collection data for retry`));
452
504
  }
453
505
  catch (error) {
454
- console.log(chalk.yellow(`Warning: Could not refresh collection data: ${error}`));
506
+ console.log(chalk.yellow(`Warning: Could not refresh collection data for retry: ${error}`));
455
507
  }
456
- // Add delay between successful attributes
457
- await delay(1000);
458
- }
459
- else {
460
- console.log(chalk.red(`❌ Failed to create attribute: ${attribute.key}`));
461
- failedAttributes.push(attribute.key);
462
508
  }
463
509
  }
464
- if (failedAttributes.length > 0) {
465
- console.log(chalk.red(`\n❌ Failed to create ${failedAttributes.length} attributes: ${failedAttributes.join(', ')}`));
510
+ // If we get here, some attributes still failed after all retries
511
+ if (attributesToProcess.length > 0) {
512
+ console.log(chalk.red(`\n❌ Failed to create ${attributesToProcess.length} attributes after ${maxOverallRetries} attempts: ${attributesToProcess.map(a => a.key).join(', ')}`));
513
+ console.log(chalk.red(`This may indicate a fundamental issue with the attribute definitions or Appwrite instance`));
466
514
  return false;
467
515
  }
468
516
  console.log(chalk.green(`\n✅ Successfully created all ${attributes.length} attributes for collection: ${collection.name}`));
@@ -130,22 +130,40 @@ export const createOrUpdateIndexWithStatusCheck = async (dbId, db, collectionId,
130
130
  */
131
131
  export const createOrUpdateIndexesWithStatusCheck = async (dbId, db, collectionId, collection, indexes) => {
132
132
  console.log(chalk.blue(`Creating/updating ${indexes.length} indexes with status monitoring...`));
133
- const failedIndexes = [];
134
- for (const index of indexes) {
135
- console.log(chalk.blue(`\n--- Processing index: ${index.key} ---`));
136
- const success = await createOrUpdateIndexWithStatusCheck(dbId, db, collectionId, collection, index);
137
- if (success) {
138
- console.log(chalk.green(`✅ Successfully created index: ${index.key}`));
139
- // Add delay between successful indexes
140
- await delay(1000);
133
+ let indexesToProcess = [...indexes];
134
+ let overallRetryCount = 0;
135
+ const maxOverallRetries = 3;
136
+ while (indexesToProcess.length > 0 && overallRetryCount < maxOverallRetries) {
137
+ const remainingIndexes = [...indexesToProcess];
138
+ indexesToProcess = []; // Reset for next iteration
139
+ console.log(chalk.blue(`\n=== Attempt ${overallRetryCount + 1}/${maxOverallRetries} - Processing ${remainingIndexes.length} indexes ===`));
140
+ for (const index of remainingIndexes) {
141
+ console.log(chalk.blue(`\n--- Processing index: ${index.key} ---`));
142
+ const success = await createOrUpdateIndexWithStatusCheck(dbId, db, collectionId, collection, index);
143
+ if (success) {
144
+ console.log(chalk.green(`✅ Successfully created index: ${index.key}`));
145
+ // Add delay between successful indexes
146
+ await delay(1000);
147
+ }
148
+ else {
149
+ console.log(chalk.red(`❌ Failed to create index: ${index.key}, will retry in next round`));
150
+ indexesToProcess.push(index); // Add back to retry list
151
+ }
152
+ }
153
+ if (indexesToProcess.length === 0) {
154
+ console.log(chalk.green(`\n✅ Successfully created all ${indexes.length} indexes`));
155
+ return true;
141
156
  }
142
- else {
143
- console.log(chalk.red(`❌ Failed to create index: ${index.key}`));
144
- failedIndexes.push(index.key);
157
+ overallRetryCount++;
158
+ if (overallRetryCount < maxOverallRetries) {
159
+ console.log(chalk.yellow(`\n⏳ Waiting 5 seconds before retrying ${indexesToProcess.length} failed indexes...`));
160
+ await delay(5000);
145
161
  }
146
162
  }
147
- if (failedIndexes.length > 0) {
148
- console.log(chalk.red(`\n❌ Failed to create ${failedIndexes.length} indexes: ${failedIndexes.join(', ')}`));
163
+ // If we get here, some indexes still failed after all retries
164
+ if (indexesToProcess.length > 0) {
165
+ console.log(chalk.red(`\n❌ Failed to create ${indexesToProcess.length} indexes after ${maxOverallRetries} attempts: ${indexesToProcess.map(i => i.key).join(', ')}`));
166
+ console.log(chalk.red(`This may indicate a fundamental issue with the index definitions or Appwrite instance`));
149
167
  return false;
150
168
  }
151
169
  console.log(chalk.green(`\n✅ Successfully created all ${indexes.length} indexes`));
@@ -1516,7 +1516,9 @@ export class InteractiveCLI {
1516
1516
  async comprehensiveTransfer() {
1517
1517
  MessageFormatter.info("Starting comprehensive transfer configuration...", { prefix: "Transfer" });
1518
1518
  try {
1519
- // Initialize controller to optionally load config if available (supports both YAML and TypeScript configs)\n await this.initControllerIfNeeded();\n \n // Check if user has an appwrite config for easier setup
1519
+ // Initialize controller to optionally load config if available (supports both YAML and TypeScript configs)
1520
+ await this.initControllerIfNeeded();
1521
+ // Check if user has an appwrite config for easier setup
1520
1522
  const hasAppwriteConfig = this.controller?.config?.appwriteEndpoint &&
1521
1523
  this.controller?.config?.appwriteProject &&
1522
1524
  this.controller?.config?.appwriteKey;
@@ -213,7 +213,9 @@ export class ComprehensiveTransfer {
213
213
  const attributesSuccess = await this.createCollectionAttributesWithStatusCheck(this.targetDatabases, dbId, targetCollection, attributesToCreate);
214
214
  if (!attributesSuccess) {
215
215
  MessageFormatter.error(`Failed to create some attributes for collection ${collection.name}`, undefined, { prefix: "Transfer" });
216
- // Continue with the transfer even if some attributes failed
216
+ MessageFormatter.error(`Skipping index creation and document transfer for collection ${collection.name} due to attribute failures`, undefined, { prefix: "Transfer" });
217
+ // Skip indexes and document transfer if attributes failed
218
+ continue;
217
219
  }
218
220
  else {
219
221
  MessageFormatter.success(`All attributes created successfully for collection ${collection.name}`, { prefix: "Transfer" });
@@ -223,7 +225,7 @@ export class ComprehensiveTransfer {
223
225
  const indexesSuccess = await this.createCollectionIndexesWithStatusCheck(dbId, this.targetDatabases, targetCollection.$id, targetCollection, collection.indexes);
224
226
  if (!indexesSuccess) {
225
227
  MessageFormatter.error(`Failed to create some indexes for collection ${collection.name}`, undefined, { prefix: "Transfer" });
226
- // Continue with the transfer even if some indexes failed
228
+ MessageFormatter.warning(`Proceeding with document transfer despite index failures for collection ${collection.name}`, { prefix: "Transfer" });
227
229
  }
228
230
  else {
229
231
  MessageFormatter.success(`All indexes created successfully for collection ${collection.name}`, { prefix: "Transfer" });
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": "1.1.1",
4
+ "version": "1.1.2",
5
5
  "main": "src/main.ts",
6
6
  "type": "module",
7
7
  "repository": {
@@ -263,26 +263,65 @@ export const createOrUpdateAttributeWithStatusCheck = async (
263
263
  return true;
264
264
  }
265
265
 
266
- // If not successful and we have retries left, delete collection and try again
266
+ // If not successful and we have retries left, delete specific attribute and try again
267
267
  if (retryCount < maxRetries) {
268
- console.log(chalk.yellow(`Attribute '${attribute.key}' failed/stuck, retrying...`));
268
+ console.log(chalk.yellow(`Attribute '${attribute.key}' failed/stuck, deleting and retrying...`));
269
269
 
270
- // Get fresh collection data
271
- const freshCollection = await db.getCollection(dbId, collection.$id);
272
-
273
- // Delete and recreate collection
274
- const newCollection = await deleteAndRecreateCollection(db, dbId, freshCollection, retryCount + 1);
275
-
276
- if (newCollection) {
277
- // Retry with the new collection
270
+ // Try to delete the specific stuck attribute instead of the entire collection
271
+ try {
272
+ await db.deleteAttribute(dbId, collection.$id, attribute.key);
273
+ console.log(chalk.yellow(`Deleted stuck attribute '${attribute.key}', will retry creation`));
274
+
275
+ // Wait a bit before retry
276
+ await delay(3000);
277
+
278
+ // Get fresh collection data
279
+ const freshCollection = await db.getCollection(dbId, collection.$id);
280
+
281
+ // Retry with the same collection (attribute should be gone now)
278
282
  return await createOrUpdateAttributeWithStatusCheck(
279
283
  db,
280
284
  dbId,
281
- newCollection,
285
+ freshCollection,
282
286
  attribute,
283
287
  retryCount + 1,
284
288
  maxRetries
285
289
  );
290
+ } catch (deleteError) {
291
+ console.log(chalk.red(`Failed to delete stuck attribute '${attribute.key}': ${deleteError}`));
292
+
293
+ // If attribute deletion fails, only then try collection recreation as last resort
294
+ if (retryCount >= maxRetries - 1) {
295
+ console.log(chalk.yellow(`Last resort: Recreating collection for attribute '${attribute.key}'`));
296
+
297
+ // Get fresh collection data
298
+ const freshCollection = await db.getCollection(dbId, collection.$id);
299
+
300
+ // Delete and recreate collection
301
+ const newCollection = await deleteAndRecreateCollection(db, dbId, freshCollection, retryCount + 1);
302
+
303
+ if (newCollection) {
304
+ // Retry with the new collection
305
+ return await createOrUpdateAttributeWithStatusCheck(
306
+ db,
307
+ dbId,
308
+ newCollection,
309
+ attribute,
310
+ retryCount + 1,
311
+ maxRetries
312
+ );
313
+ }
314
+ } else {
315
+ // Continue to next retry without collection recreation
316
+ return await createOrUpdateAttributeWithStatusCheck(
317
+ db,
318
+ dbId,
319
+ collection,
320
+ attribute,
321
+ retryCount + 1,
322
+ maxRetries
323
+ );
324
+ }
286
325
  }
287
326
  }
288
327
 
@@ -810,42 +849,73 @@ export const createUpdateCollectionAttributesWithStatusCheck = async (
810
849
  }
811
850
  }
812
851
 
813
- // Create attributes ONE BY ONE with proper status checking
852
+ // Create attributes ONE BY ONE with proper status checking and persistent retry logic
814
853
  console.log(chalk.blue(`Creating ${attributes.length} attributes sequentially with status monitoring...`));
815
854
 
816
855
  let currentCollection = collection;
817
- const failedAttributes: string[] = [];
856
+ let attributesToProcess = [...attributes];
857
+ let overallRetryCount = 0;
858
+ const maxOverallRetries = 3;
818
859
 
819
- for (const attribute of attributes) {
820
- console.log(chalk.blue(`\n--- Processing attribute: ${attribute.key} ---`));
860
+ while (attributesToProcess.length > 0 && overallRetryCount < maxOverallRetries) {
861
+ const remainingAttributes = [...attributesToProcess];
862
+ attributesToProcess = []; // Reset for next iteration
821
863
 
822
- const success = await createOrUpdateAttributeWithStatusCheck(
823
- db,
824
- dbId,
825
- currentCollection,
826
- attribute
827
- );
864
+ console.log(chalk.blue(`\n=== Attempt ${overallRetryCount + 1}/${maxOverallRetries} - Processing ${remainingAttributes.length} attributes ===`));
828
865
 
829
- if (success) {
830
- console.log(chalk.green(`✅ Successfully created attribute: ${attribute.key}`));
866
+ for (const attribute of remainingAttributes) {
867
+ console.log(chalk.blue(`\n--- Processing attribute: ${attribute.key} ---`));
868
+
869
+ const success = await createOrUpdateAttributeWithStatusCheck(
870
+ db,
871
+ dbId,
872
+ currentCollection,
873
+ attribute
874
+ );
875
+
876
+ if (success) {
877
+ console.log(chalk.green(`✅ Successfully created attribute: ${attribute.key}`));
878
+
879
+ // Get updated collection data for next iteration
880
+ try {
881
+ currentCollection = await db.getCollection(dbId, collection.$id);
882
+ } catch (error) {
883
+ console.log(chalk.yellow(`Warning: Could not refresh collection data: ${error}`));
884
+ }
885
+
886
+ // Add delay between successful attributes
887
+ await delay(1000);
888
+ } else {
889
+ console.log(chalk.red(`❌ Failed to create attribute: ${attribute.key}, will retry in next round`));
890
+ attributesToProcess.push(attribute); // Add back to retry list
891
+ }
892
+ }
893
+
894
+ if (attributesToProcess.length === 0) {
895
+ console.log(chalk.green(`\n✅ Successfully created all ${attributes.length} attributes for collection: ${collection.name}`));
896
+ return true;
897
+ }
898
+
899
+ overallRetryCount++;
900
+
901
+ if (overallRetryCount < maxOverallRetries) {
902
+ console.log(chalk.yellow(`\n⏳ Waiting 5 seconds before retrying ${attributesToProcess.length} failed attributes...`));
903
+ await delay(5000);
831
904
 
832
- // Get updated collection data for next iteration
905
+ // Refresh collection data before retry
833
906
  try {
834
907
  currentCollection = await db.getCollection(dbId, collection.$id);
908
+ console.log(chalk.blue(`Refreshed collection data for retry`));
835
909
  } catch (error) {
836
- console.log(chalk.yellow(`Warning: Could not refresh collection data: ${error}`));
910
+ console.log(chalk.yellow(`Warning: Could not refresh collection data for retry: ${error}`));
837
911
  }
838
-
839
- // Add delay between successful attributes
840
- await delay(1000);
841
- } else {
842
- console.log(chalk.red(`❌ Failed to create attribute: ${attribute.key}`));
843
- failedAttributes.push(attribute.key);
844
912
  }
845
913
  }
846
914
 
847
- if (failedAttributes.length > 0) {
848
- console.log(chalk.red(`\n❌ Failed to create ${failedAttributes.length} attributes: ${failedAttributes.join(', ')}`));
915
+ // If we get here, some attributes still failed after all retries
916
+ if (attributesToProcess.length > 0) {
917
+ console.log(chalk.red(`\n❌ Failed to create ${attributesToProcess.length} attributes after ${maxOverallRetries} attempts: ${attributesToProcess.map(a => a.key).join(', ')}`));
918
+ console.log(chalk.red(`This may indicate a fundamental issue with the attribute definitions or Appwrite instance`));
849
919
  return false;
850
920
  }
851
921
 
@@ -233,32 +233,55 @@ export const createOrUpdateIndexesWithStatusCheck = async (
233
233
  ): Promise<boolean> => {
234
234
  console.log(chalk.blue(`Creating/updating ${indexes.length} indexes with status monitoring...`));
235
235
 
236
- const failedIndexes: string[] = [];
236
+ let indexesToProcess = [...indexes];
237
+ let overallRetryCount = 0;
238
+ const maxOverallRetries = 3;
237
239
 
238
- for (const index of indexes) {
239
- console.log(chalk.blue(`\n--- Processing index: ${index.key} ---`));
240
+ while (indexesToProcess.length > 0 && overallRetryCount < maxOverallRetries) {
241
+ const remainingIndexes = [...indexesToProcess];
242
+ indexesToProcess = []; // Reset for next iteration
240
243
 
241
- const success = await createOrUpdateIndexWithStatusCheck(
242
- dbId,
243
- db,
244
- collectionId,
245
- collection,
246
- index
247
- );
244
+ console.log(chalk.blue(`\n=== Attempt ${overallRetryCount + 1}/${maxOverallRetries} - Processing ${remainingIndexes.length} indexes ===`));
248
245
 
249
- if (success) {
250
- console.log(chalk.green(`✅ Successfully created index: ${index.key}`));
246
+ for (const index of remainingIndexes) {
247
+ console.log(chalk.blue(`\n--- Processing index: ${index.key} ---`));
251
248
 
252
- // Add delay between successful indexes
253
- await delay(1000);
254
- } else {
255
- console.log(chalk.red(`❌ Failed to create index: ${index.key}`));
256
- failedIndexes.push(index.key);
249
+ const success = await createOrUpdateIndexWithStatusCheck(
250
+ dbId,
251
+ db,
252
+ collectionId,
253
+ collection,
254
+ index
255
+ );
256
+
257
+ if (success) {
258
+ console.log(chalk.green(`✅ Successfully created index: ${index.key}`));
259
+
260
+ // Add delay between successful indexes
261
+ await delay(1000);
262
+ } else {
263
+ console.log(chalk.red(`❌ Failed to create index: ${index.key}, will retry in next round`));
264
+ indexesToProcess.push(index); // Add back to retry list
265
+ }
266
+ }
267
+
268
+ if (indexesToProcess.length === 0) {
269
+ console.log(chalk.green(`\n✅ Successfully created all ${indexes.length} indexes`));
270
+ return true;
271
+ }
272
+
273
+ overallRetryCount++;
274
+
275
+ if (overallRetryCount < maxOverallRetries) {
276
+ console.log(chalk.yellow(`\n⏳ Waiting 5 seconds before retrying ${indexesToProcess.length} failed indexes...`));
277
+ await delay(5000);
257
278
  }
258
279
  }
259
280
 
260
- if (failedIndexes.length > 0) {
261
- console.log(chalk.red(`\n❌ Failed to create ${failedIndexes.length} indexes: ${failedIndexes.join(', ')}`));
281
+ // If we get here, some indexes still failed after all retries
282
+ if (indexesToProcess.length > 0) {
283
+ console.log(chalk.red(`\n❌ Failed to create ${indexesToProcess.length} indexes after ${maxOverallRetries} attempts: ${indexesToProcess.map(i => i.key).join(', ')}`));
284
+ console.log(chalk.red(`This may indicate a fundamental issue with the index definitions or Appwrite instance`));
262
285
  return false;
263
286
  }
264
287
 
@@ -2052,7 +2052,10 @@ export class InteractiveCLI {
2052
2052
  MessageFormatter.info("Starting comprehensive transfer configuration...", { prefix: "Transfer" });
2053
2053
 
2054
2054
  try {
2055
- // Initialize controller to optionally load config if available (supports both YAML and TypeScript configs)\n await this.initControllerIfNeeded();\n \n // Check if user has an appwrite config for easier setup
2055
+ // Initialize controller to optionally load config if available (supports both YAML and TypeScript configs)
2056
+ await this.initControllerIfNeeded();
2057
+
2058
+ // Check if user has an appwrite config for easier setup
2056
2059
  const hasAppwriteConfig = this.controller?.config?.appwriteEndpoint &&
2057
2060
  this.controller?.config?.appwriteProject &&
2058
2061
  this.controller?.config?.appwriteKey;
@@ -331,7 +331,9 @@ export class ComprehensiveTransfer {
331
331
 
332
332
  if (!attributesSuccess) {
333
333
  MessageFormatter.error(`Failed to create some attributes for collection ${collection.name}`, undefined, { prefix: "Transfer" });
334
- // Continue with the transfer even if some attributes failed
334
+ MessageFormatter.error(`Skipping index creation and document transfer for collection ${collection.name} due to attribute failures`, undefined, { prefix: "Transfer" });
335
+ // Skip indexes and document transfer if attributes failed
336
+ continue;
335
337
  } else {
336
338
  MessageFormatter.success(`All attributes created successfully for collection ${collection.name}`, { prefix: "Transfer" });
337
339
  }
@@ -349,7 +351,7 @@ export class ComprehensiveTransfer {
349
351
 
350
352
  if (!indexesSuccess) {
351
353
  MessageFormatter.error(`Failed to create some indexes for collection ${collection.name}`, undefined, { prefix: "Transfer" });
352
- // Continue with the transfer even if some indexes failed
354
+ MessageFormatter.warning(`Proceeding with document transfer despite index failures for collection ${collection.name}`, { prefix: "Transfer" });
353
355
  } else {
354
356
  MessageFormatter.success(`All indexes created successfully for collection ${collection.name}`, { prefix: "Transfer" });
355
357
  }