appwrite-utils-cli 1.5.2 → 1.6.1
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/CHANGELOG.md +199 -0
- package/README.md +251 -29
- package/dist/adapters/AdapterFactory.d.ts +10 -3
- package/dist/adapters/AdapterFactory.js +213 -17
- package/dist/adapters/TablesDBAdapter.js +60 -17
- package/dist/backups/operations/bucketBackup.d.ts +19 -0
- package/dist/backups/operations/bucketBackup.js +197 -0
- package/dist/backups/operations/collectionBackup.d.ts +30 -0
- package/dist/backups/operations/collectionBackup.js +201 -0
- package/dist/backups/operations/comprehensiveBackup.d.ts +25 -0
- package/dist/backups/operations/comprehensiveBackup.js +238 -0
- package/dist/backups/schemas/bucketManifest.d.ts +93 -0
- package/dist/backups/schemas/bucketManifest.js +33 -0
- package/dist/backups/schemas/comprehensiveManifest.d.ts +108 -0
- package/dist/backups/schemas/comprehensiveManifest.js +32 -0
- package/dist/backups/tracking/centralizedTracking.d.ts +34 -0
- package/dist/backups/tracking/centralizedTracking.js +274 -0
- package/dist/cli/commands/configCommands.d.ts +8 -0
- package/dist/cli/commands/configCommands.js +160 -0
- package/dist/cli/commands/databaseCommands.d.ts +13 -0
- package/dist/cli/commands/databaseCommands.js +479 -0
- package/dist/cli/commands/functionCommands.d.ts +7 -0
- package/dist/cli/commands/functionCommands.js +289 -0
- package/dist/cli/commands/schemaCommands.d.ts +7 -0
- package/dist/cli/commands/schemaCommands.js +134 -0
- package/dist/cli/commands/transferCommands.d.ts +5 -0
- package/dist/cli/commands/transferCommands.js +384 -0
- package/dist/collections/attributes.d.ts +5 -4
- package/dist/collections/attributes.js +539 -246
- package/dist/collections/indexes.js +39 -37
- package/dist/collections/methods.d.ts +2 -16
- package/dist/collections/methods.js +90 -538
- package/dist/collections/transferOperations.d.ts +7 -0
- package/dist/collections/transferOperations.js +331 -0
- package/dist/collections/wipeOperations.d.ts +16 -0
- package/dist/collections/wipeOperations.js +328 -0
- package/dist/config/configMigration.d.ts +87 -0
- package/dist/config/configMigration.js +390 -0
- package/dist/config/configValidation.d.ts +66 -0
- package/dist/config/configValidation.js +358 -0
- package/dist/config/yamlConfig.d.ts +455 -1
- package/dist/config/yamlConfig.js +145 -52
- package/dist/databases/methods.js +3 -2
- package/dist/databases/setup.d.ts +1 -2
- package/dist/databases/setup.js +9 -87
- package/dist/examples/yamlTerminologyExample.d.ts +42 -0
- package/dist/examples/yamlTerminologyExample.js +269 -0
- package/dist/functions/deployments.js +11 -10
- package/dist/functions/methods.d.ts +1 -1
- package/dist/functions/methods.js +5 -4
- package/dist/init.js +9 -9
- package/dist/interactiveCLI.d.ts +8 -17
- package/dist/interactiveCLI.js +209 -1172
- package/dist/main.js +364 -21
- package/dist/migrations/afterImportActions.js +22 -30
- package/dist/migrations/appwriteToX.js +71 -25
- package/dist/migrations/dataLoader.js +35 -26
- package/dist/migrations/importController.js +29 -30
- package/dist/migrations/relationships.js +13 -12
- package/dist/migrations/services/ImportOrchestrator.js +16 -19
- package/dist/migrations/transfer.js +46 -46
- package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +3 -1
- package/dist/migrations/yaml/YamlImportConfigLoader.js +6 -3
- package/dist/migrations/yaml/YamlImportIntegration.d.ts +9 -3
- package/dist/migrations/yaml/YamlImportIntegration.js +22 -11
- package/dist/migrations/yaml/generateImportSchemas.d.ts +14 -1
- package/dist/migrations/yaml/generateImportSchemas.js +736 -7
- package/dist/schemas/authUser.d.ts +1 -1
- package/dist/setupController.js +3 -2
- package/dist/shared/backupMetadataSchema.d.ts +94 -0
- package/dist/shared/backupMetadataSchema.js +38 -0
- package/dist/shared/backupTracking.d.ts +18 -0
- package/dist/shared/backupTracking.js +176 -0
- package/dist/shared/confirmationDialogs.js +15 -15
- package/dist/shared/errorUtils.d.ts +54 -0
- package/dist/shared/errorUtils.js +95 -0
- package/dist/shared/functionManager.js +20 -19
- package/dist/shared/indexManager.js +12 -11
- package/dist/shared/jsonSchemaGenerator.js +10 -26
- package/dist/shared/logging.d.ts +51 -0
- package/dist/shared/logging.js +70 -0
- package/dist/shared/messageFormatter.d.ts +2 -0
- package/dist/shared/messageFormatter.js +10 -0
- package/dist/shared/migrationHelpers.d.ts +6 -16
- package/dist/shared/migrationHelpers.js +24 -21
- package/dist/shared/operationLogger.d.ts +8 -1
- package/dist/shared/operationLogger.js +11 -24
- package/dist/shared/operationQueue.d.ts +28 -1
- package/dist/shared/operationQueue.js +268 -66
- package/dist/shared/operationsTable.d.ts +26 -0
- package/dist/shared/operationsTable.js +286 -0
- package/dist/shared/operationsTableSchema.d.ts +48 -0
- package/dist/shared/operationsTableSchema.js +35 -0
- package/dist/shared/relationshipExtractor.d.ts +56 -0
- package/dist/shared/relationshipExtractor.js +138 -0
- package/dist/shared/schemaGenerator.d.ts +19 -1
- package/dist/shared/schemaGenerator.js +56 -75
- package/dist/storage/backupCompression.d.ts +20 -0
- package/dist/storage/backupCompression.js +67 -0
- package/dist/storage/methods.d.ts +16 -2
- package/dist/storage/methods.js +98 -14
- package/dist/users/methods.js +9 -8
- package/dist/utils/configDiscovery.d.ts +78 -0
- package/dist/utils/configDiscovery.js +430 -0
- package/dist/utils/directoryUtils.d.ts +22 -0
- package/dist/utils/directoryUtils.js +59 -0
- package/dist/utils/getClientFromConfig.d.ts +17 -8
- package/dist/utils/getClientFromConfig.js +162 -17
- package/dist/utils/helperFunctions.d.ts +16 -2
- package/dist/utils/helperFunctions.js +19 -5
- package/dist/utils/loadConfigs.d.ts +34 -9
- package/dist/utils/loadConfigs.js +236 -316
- package/dist/utils/pathResolvers.d.ts +53 -0
- package/dist/utils/pathResolvers.js +72 -0
- package/dist/utils/projectConfig.d.ts +119 -0
- package/dist/utils/projectConfig.js +171 -0
- package/dist/utils/retryFailedPromises.js +4 -2
- package/dist/utils/sessionAuth.d.ts +48 -0
- package/dist/utils/sessionAuth.js +164 -0
- package/dist/utils/sessionPreservationExample.d.ts +1666 -0
- package/dist/utils/sessionPreservationExample.js +101 -0
- package/dist/utils/setupFiles.js +301 -41
- package/dist/utils/typeGuards.d.ts +35 -0
- package/dist/utils/typeGuards.js +57 -0
- package/dist/utils/versionDetection.js +145 -9
- package/dist/utils/yamlConverter.d.ts +53 -3
- package/dist/utils/yamlConverter.js +232 -13
- package/dist/utils/yamlLoader.d.ts +70 -0
- package/dist/utils/yamlLoader.js +263 -0
- package/dist/utilsController.d.ts +36 -3
- package/dist/utilsController.js +186 -56
- package/package.json +12 -2
- package/src/adapters/AdapterFactory.ts +263 -35
- package/src/adapters/TablesDBAdapter.ts +225 -36
- package/src/backups/operations/bucketBackup.ts +277 -0
- package/src/backups/operations/collectionBackup.ts +310 -0
- package/src/backups/operations/comprehensiveBackup.ts +342 -0
- package/src/backups/schemas/bucketManifest.ts +78 -0
- package/src/backups/schemas/comprehensiveManifest.ts +76 -0
- package/src/backups/tracking/centralizedTracking.ts +352 -0
- package/src/cli/commands/configCommands.ts +194 -0
- package/src/cli/commands/databaseCommands.ts +635 -0
- package/src/cli/commands/functionCommands.ts +379 -0
- package/src/cli/commands/schemaCommands.ts +163 -0
- package/src/cli/commands/transferCommands.ts +457 -0
- package/src/collections/attributes.ts +900 -621
- package/src/collections/attributes.ts.backup +1555 -0
- package/src/collections/indexes.ts +116 -114
- package/src/collections/methods.ts +295 -968
- package/src/collections/transferOperations.ts +516 -0
- package/src/collections/wipeOperations.ts +501 -0
- package/src/config/README.md +274 -0
- package/src/config/configMigration.ts +575 -0
- package/src/config/configValidation.ts +445 -0
- package/src/config/yamlConfig.ts +168 -55
- package/src/databases/methods.ts +3 -2
- package/src/databases/setup.ts +11 -138
- package/src/examples/yamlTerminologyExample.ts +341 -0
- package/src/functions/deployments.ts +14 -12
- package/src/functions/methods.ts +11 -11
- package/src/functions/templates/hono-typescript/README.md +286 -0
- package/src/functions/templates/hono-typescript/package.json +26 -0
- package/src/functions/templates/hono-typescript/src/adapters/request.ts +74 -0
- package/src/functions/templates/hono-typescript/src/adapters/response.ts +106 -0
- package/src/functions/templates/hono-typescript/src/app.ts +180 -0
- package/src/functions/templates/hono-typescript/src/context.ts +103 -0
- package/src/functions/templates/hono-typescript/src/index.ts +54 -0
- package/src/functions/templates/hono-typescript/src/middleware/appwrite.ts +119 -0
- package/src/functions/templates/hono-typescript/tsconfig.json +20 -0
- package/src/functions/templates/typescript-node/package.json +2 -1
- package/src/functions/templates/typescript-node/src/context.ts +103 -0
- package/src/functions/templates/typescript-node/src/index.ts +18 -12
- package/src/functions/templates/uv/pyproject.toml +1 -0
- package/src/functions/templates/uv/src/context.py +125 -0
- package/src/functions/templates/uv/src/index.py +35 -5
- package/src/init.ts +9 -11
- package/src/interactiveCLI.ts +274 -1563
- package/src/main.ts +418 -24
- package/src/migrations/afterImportActions.ts +71 -44
- package/src/migrations/appwriteToX.ts +100 -34
- package/src/migrations/dataLoader.ts +48 -34
- package/src/migrations/importController.ts +44 -39
- package/src/migrations/relationships.ts +28 -18
- package/src/migrations/services/ImportOrchestrator.ts +24 -27
- package/src/migrations/transfer.ts +159 -121
- package/src/migrations/yaml/YamlImportConfigLoader.ts +11 -4
- package/src/migrations/yaml/YamlImportIntegration.ts +47 -20
- package/src/migrations/yaml/generateImportSchemas.ts +751 -12
- package/src/setupController.ts +3 -2
- package/src/shared/backupMetadataSchema.ts +93 -0
- package/src/shared/backupTracking.ts +211 -0
- package/src/shared/confirmationDialogs.ts +19 -19
- package/src/shared/errorUtils.ts +110 -0
- package/src/shared/functionManager.ts +21 -20
- package/src/shared/indexManager.ts +12 -11
- package/src/shared/jsonSchemaGenerator.ts +38 -52
- package/src/shared/logging.ts +75 -0
- package/src/shared/messageFormatter.ts +14 -1
- package/src/shared/migrationHelpers.ts +45 -38
- package/src/shared/operationLogger.ts +11 -36
- package/src/shared/operationQueue.ts +322 -93
- package/src/shared/operationsTable.ts +338 -0
- package/src/shared/operationsTableSchema.ts +60 -0
- package/src/shared/relationshipExtractor.ts +214 -0
- package/src/shared/schemaGenerator.ts +179 -219
- package/src/storage/backupCompression.ts +88 -0
- package/src/storage/methods.ts +131 -34
- package/src/users/methods.ts +11 -9
- package/src/utils/configDiscovery.ts +502 -0
- package/src/utils/directoryUtils.ts +61 -0
- package/src/utils/getClientFromConfig.ts +205 -22
- package/src/utils/helperFunctions.ts +23 -5
- package/src/utils/loadConfigs.ts +313 -345
- package/src/utils/pathResolvers.ts +81 -0
- package/src/utils/projectConfig.ts +299 -0
- package/src/utils/retryFailedPromises.ts +4 -2
- package/src/utils/sessionAuth.ts +230 -0
- package/src/utils/setupFiles.ts +322 -54
- package/src/utils/typeGuards.ts +65 -0
- package/src/utils/versionDetection.ts +218 -64
- package/src/utils/yamlConverter.ts +296 -13
- package/src/utils/yamlLoader.ts +364 -0
- package/src/utilsController.ts +314 -110
- package/tests/README.md +497 -0
- package/tests/adapters/AdapterFactory.test.ts +277 -0
- package/tests/integration/syncOperations.test.ts +463 -0
- package/tests/jest.config.js +25 -0
- package/tests/migration/configMigration.test.ts +546 -0
- package/tests/setup.ts +62 -0
- package/tests/testUtils.ts +340 -0
- package/tests/utils/loadConfigs.test.ts +350 -0
- package/tests/validation/configValidation.test.ts +412 -0
- package/src/utils/schemaStrings.ts +0 -517
@@ -1,8 +1,9 @@
|
|
1
|
-
import { indexSchema, type Index } from "appwrite-utils";
|
2
|
-
import { Databases, IndexType, Query, type Models } from "node-appwrite";
|
3
|
-
import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
|
4
|
-
import { delay, tryAwaitWithRetry } from "../utils/helperFunctions.js";
|
5
|
-
import
|
1
|
+
import { indexSchema, type Index } from "appwrite-utils";
|
2
|
+
import { Databases, IndexType, Query, type Models } from "node-appwrite";
|
3
|
+
import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
|
4
|
+
import { delay, tryAwaitWithRetry, calculateExponentialBackoff } from "../utils/helperFunctions.js";
|
5
|
+
import { isLegacyDatabases } from "../utils/typeGuards.js";
|
6
|
+
import { MessageFormatter } from "../shared/messageFormatter.js";
|
6
7
|
|
7
8
|
// Interface for index with status
|
8
9
|
interface IndexWithStatus {
|
@@ -19,90 +20,90 @@ interface IndexWithStatus {
|
|
19
20
|
/**
|
20
21
|
* Wait for index to become available, with retry logic for stuck indexes and exponential backoff
|
21
22
|
*/
|
22
|
-
const waitForIndexAvailable = async (
|
23
|
-
db: Databases | DatabaseAdapter,
|
24
|
-
dbId: string,
|
25
|
-
collectionId: string,
|
26
|
-
indexKey: string,
|
27
|
-
maxWaitTime: number = 60000, // 1 minute
|
28
|
-
retryCount: number = 0,
|
29
|
-
maxRetries: number = 5
|
30
|
-
): Promise<boolean> => {
|
23
|
+
const waitForIndexAvailable = async (
|
24
|
+
db: Databases | DatabaseAdapter,
|
25
|
+
dbId: string,
|
26
|
+
collectionId: string,
|
27
|
+
indexKey: string,
|
28
|
+
maxWaitTime: number = 60000, // 1 minute
|
29
|
+
retryCount: number = 0,
|
30
|
+
maxRetries: number = 5
|
31
|
+
): Promise<boolean> => {
|
31
32
|
const startTime = Date.now();
|
32
33
|
let checkInterval = 2000; // Start with 2 seconds
|
33
34
|
|
34
35
|
// Calculate exponential backoff: 2s, 4s, 8s, 16s, 30s (capped at 30s)
|
35
36
|
if (retryCount > 0) {
|
36
|
-
const exponentialDelay =
|
37
|
-
|
37
|
+
const exponentialDelay = calculateExponentialBackoff(retryCount);
|
38
|
+
MessageFormatter.info(`Waiting for index '${indexKey}' to become available (retry ${retryCount}, backoff: ${exponentialDelay}ms)...`);
|
38
39
|
await delay(exponentialDelay);
|
39
40
|
} else {
|
40
|
-
|
41
|
+
MessageFormatter.info(`Waiting for index '${indexKey}' to become available...`);
|
41
42
|
}
|
42
43
|
|
43
44
|
while (Date.now() - startTime < maxWaitTime) {
|
44
45
|
try {
|
45
|
-
const indexList = await (db
|
46
|
-
? db.listIndexes(dbId, collectionId)
|
47
|
-
: (db as DatabaseAdapter).listIndexes({ databaseId: dbId, tableId: collectionId }));
|
48
|
-
const indexes: any[] = (db
|
49
|
-
? (indexList as any).indexes
|
50
|
-
: ((indexList as any).data || (indexList as any).indexes || []);
|
51
|
-
const index = indexes.find((idx: any) => idx.key === indexKey) as IndexWithStatus | undefined;
|
52
|
-
|
46
|
+
const indexList = await (isLegacyDatabases(db)
|
47
|
+
? db.listIndexes(dbId, collectionId)
|
48
|
+
: (db as DatabaseAdapter).listIndexes({ databaseId: dbId, tableId: collectionId }));
|
49
|
+
const indexes: any[] = isLegacyDatabases(db)
|
50
|
+
? (indexList as any).indexes
|
51
|
+
: ((indexList as any).data || (indexList as any).indexes || []);
|
52
|
+
const index = indexes.find((idx: any) => idx.key === indexKey) as IndexWithStatus | undefined;
|
53
|
+
|
53
54
|
if (!index) {
|
54
|
-
|
55
|
+
MessageFormatter.error(`Index '${indexKey}' not found in database '${dbId}' collection '${collectionId}'`);
|
55
56
|
return false;
|
56
57
|
}
|
57
|
-
|
58
|
-
if (db
|
59
|
-
|
60
|
-
} else {
|
61
|
-
|
62
|
-
}
|
58
|
+
|
59
|
+
if (isLegacyDatabases(db)) {
|
60
|
+
MessageFormatter.debug(`Index '${indexKey}' status: ${(index as any).status}`);
|
61
|
+
} else {
|
62
|
+
MessageFormatter.debug(`Index '${indexKey}' detected (TablesDB)`);
|
63
|
+
}
|
63
64
|
|
64
65
|
switch (index.status) {
|
65
|
-
case 'available':
|
66
|
-
|
67
|
-
return true;
|
68
|
-
|
66
|
+
case 'available':
|
67
|
+
MessageFormatter.success(`Index '${indexKey}' is now available (type: ${index.type}, attributes: [${index.attributes.join(', ')}])`);
|
68
|
+
return true;
|
69
|
+
|
69
70
|
case 'failed':
|
70
|
-
|
71
|
+
MessageFormatter.error(`Index '${indexKey}' failed: ${index.error} (type: ${index.type}, attributes: [${index.attributes.join(', ')}])`);
|
71
72
|
return false;
|
72
|
-
|
73
|
+
|
73
74
|
case 'stuck':
|
74
|
-
|
75
|
+
MessageFormatter.warning(`Index '${indexKey}' is stuck, will retry... (type: ${index.type}, attributes: [${index.attributes.join(', ')}])`);
|
75
76
|
return false;
|
76
|
-
|
77
|
-
case 'processing':
|
78
|
-
// Continue waiting
|
79
|
-
break;
|
80
|
-
|
77
|
+
|
78
|
+
case 'processing':
|
79
|
+
// Continue waiting
|
80
|
+
break;
|
81
|
+
|
81
82
|
case 'deleting':
|
82
|
-
|
83
|
+
MessageFormatter.warning(`Index '${indexKey}' is being deleted`);
|
83
84
|
break;
|
84
|
-
|
85
|
+
|
85
86
|
default:
|
86
|
-
|
87
|
+
MessageFormatter.warning(`Unknown status '${index.status}' for index '${indexKey}'`);
|
87
88
|
break;
|
88
89
|
}
|
89
90
|
|
90
|
-
await delay(checkInterval);
|
91
|
-
} catch (error) {
|
92
|
-
|
93
|
-
return false;
|
94
|
-
}
|
95
|
-
}
|
96
|
-
|
91
|
+
await delay(checkInterval);
|
92
|
+
} catch (error) {
|
93
|
+
MessageFormatter.error(`Error checking index '${indexKey}' status in database '${dbId}' collection '${collectionId}': ${error}`);
|
94
|
+
return false;
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
97
98
|
// Timeout reached
|
98
|
-
|
99
|
-
|
99
|
+
MessageFormatter.warning(`Timeout waiting for index '${indexKey}' (${maxWaitTime}ms)`);
|
100
|
+
|
100
101
|
// If we have retries left and this isn't the last retry, try recreating
|
101
102
|
if (retryCount < maxRetries) {
|
102
|
-
|
103
|
+
MessageFormatter.info(`Retrying index '${indexKey}' creation (attempt ${retryCount + 1}/${maxRetries})`);
|
103
104
|
return false; // Signal that we need to retry
|
104
105
|
}
|
105
|
-
|
106
|
+
|
106
107
|
return false;
|
107
108
|
};
|
108
109
|
|
@@ -119,7 +120,7 @@ export const createOrUpdateIndexWithStatusCheck = async (
|
|
119
120
|
retryCount: number = 0,
|
120
121
|
maxRetries: number = 3,
|
121
122
|
): Promise<boolean> => {
|
122
|
-
|
123
|
+
MessageFormatter.info(`Creating/updating index '${index.key}' (attempt ${retryCount + 1}/${maxRetries + 1}) - type: ${index.type}, attributes: [${index.attributes.join(', ')}]`);
|
123
124
|
|
124
125
|
try {
|
125
126
|
// First, validate that all required attributes exist
|
@@ -127,10 +128,10 @@ export const createOrUpdateIndexWithStatusCheck = async (
|
|
127
128
|
const existingAttributeKeys = freshCollection.attributes.map((attr: any) => attr.key);
|
128
129
|
|
129
130
|
const missingAttributes = index.attributes.filter(attr => !existingAttributeKeys.includes(attr));
|
130
|
-
|
131
|
+
|
131
132
|
if (missingAttributes.length > 0) {
|
132
|
-
|
133
|
-
|
133
|
+
MessageFormatter.error(`Index '${index.key}' cannot be created: missing attributes [${missingAttributes.join(', ')}] (type: ${index.type})`);
|
134
|
+
MessageFormatter.error(`Available attributes: [${existingAttributeKeys.join(', ')}]`);
|
134
135
|
return false; // Don't retry if attributes are missing
|
135
136
|
}
|
136
137
|
|
@@ -154,56 +155,56 @@ export const createOrUpdateIndexWithStatusCheck = async (
|
|
154
155
|
|
155
156
|
// If not successful and we have retries left, just retry the index creation
|
156
157
|
if (retryCount < maxRetries) {
|
157
|
-
|
158
|
-
|
158
|
+
MessageFormatter.warning(`Index '${index.key}' failed/stuck, retrying (${retryCount + 1}/${maxRetries}) - type: ${index.type}, attributes: [${index.attributes.join(', ')}]`);
|
159
|
+
|
159
160
|
// Wait a bit before retry
|
160
161
|
await new Promise(resolve => setTimeout(resolve, 2000 * (retryCount + 1)));
|
161
|
-
|
162
|
+
|
162
163
|
// Retry the index creation
|
163
164
|
return await createOrUpdateIndexWithStatusCheck(
|
164
|
-
dbId,
|
165
|
-
db,
|
166
|
-
collectionId,
|
167
|
-
collection,
|
168
|
-
index,
|
169
|
-
retryCount + 1,
|
165
|
+
dbId,
|
166
|
+
db,
|
167
|
+
collectionId,
|
168
|
+
collection,
|
169
|
+
index,
|
170
|
+
retryCount + 1,
|
170
171
|
maxRetries
|
171
172
|
);
|
172
173
|
}
|
173
|
-
|
174
|
-
|
174
|
+
|
175
|
+
MessageFormatter.error(`Failed to create index '${index.key}' after ${maxRetries + 1} attempts (type: ${index.type}, attributes: [${index.attributes.join(', ')}])`);
|
175
176
|
return false;
|
176
177
|
|
177
178
|
} catch (error) {
|
178
179
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
179
|
-
|
180
|
-
|
180
|
+
MessageFormatter.error(`Error creating index '${index.key}': ${errorMessage} (type: ${index.type}, attributes: [${index.attributes.join(', ')}])`);
|
181
|
+
|
181
182
|
// Check if this is a permanent error that shouldn't be retried
|
182
|
-
if (errorMessage.toLowerCase().includes('not found') ||
|
183
|
-
errorMessage.toLowerCase().includes('missing') ||
|
183
|
+
if (errorMessage.toLowerCase().includes('not found') ||
|
184
|
+
errorMessage.toLowerCase().includes('missing') ||
|
184
185
|
errorMessage.toLowerCase().includes('does not exist') ||
|
185
186
|
errorMessage.toLowerCase().includes('attribute') && errorMessage.toLowerCase().includes('not found')) {
|
186
|
-
|
187
|
+
MessageFormatter.error(`Index '${index.key}' has permanent error - not retrying (type: ${index.type})`);
|
187
188
|
return false;
|
188
189
|
}
|
189
|
-
|
190
|
+
|
190
191
|
if (retryCount < maxRetries) {
|
191
|
-
|
192
|
-
|
192
|
+
MessageFormatter.warning(`Retrying index '${index.key}' due to error... (type: ${index.type}, attributes: [${index.attributes.join(', ')}])`);
|
193
|
+
|
193
194
|
// Wait a bit before retry
|
194
195
|
await delay(2000);
|
195
|
-
|
196
|
+
|
196
197
|
return await createOrUpdateIndexWithStatusCheck(
|
197
|
-
dbId,
|
198
|
-
db,
|
199
|
-
collectionId,
|
200
|
-
collection,
|
201
|
-
index,
|
202
|
-
retryCount + 1,
|
198
|
+
dbId,
|
199
|
+
db,
|
200
|
+
collectionId,
|
201
|
+
collection,
|
202
|
+
index,
|
203
|
+
retryCount + 1,
|
203
204
|
maxRetries
|
204
205
|
);
|
205
206
|
}
|
206
|
-
|
207
|
+
|
207
208
|
return false;
|
208
209
|
}
|
209
210
|
};
|
@@ -218,61 +219,62 @@ export const createOrUpdateIndexesWithStatusCheck = async (
|
|
218
219
|
collection: Models.Collection,
|
219
220
|
indexes: Index[]
|
220
221
|
): Promise<boolean> => {
|
221
|
-
|
222
|
-
|
222
|
+
MessageFormatter.info(`Creating/updating ${indexes.length} indexes with status monitoring for collection '${collectionId}'`);
|
223
|
+
|
223
224
|
let indexesToProcess = [...indexes];
|
224
225
|
let overallRetryCount = 0;
|
225
226
|
const maxOverallRetries = 3;
|
226
|
-
|
227
|
+
|
227
228
|
while (indexesToProcess.length > 0 && overallRetryCount < maxOverallRetries) {
|
228
229
|
const remainingIndexes = [...indexesToProcess];
|
229
230
|
indexesToProcess = []; // Reset for next iteration
|
230
|
-
|
231
|
-
|
231
|
+
|
232
|
+
MessageFormatter.info(`\n=== Attempt ${overallRetryCount + 1}/${maxOverallRetries} - Processing ${remainingIndexes.length} indexes ===`);
|
232
233
|
|
233
234
|
for (const index of remainingIndexes) {
|
234
|
-
|
235
|
-
|
235
|
+
MessageFormatter.info(`\n--- Processing index: ${index.key} (type: ${index.type}, attributes: [${index.attributes.join(', ')}]) ---`);
|
236
|
+
|
236
237
|
const success = await createOrUpdateIndexWithStatusCheck(
|
237
|
-
dbId,
|
238
|
-
db,
|
239
|
-
collectionId,
|
240
|
-
collection,
|
238
|
+
dbId,
|
239
|
+
db,
|
240
|
+
collectionId,
|
241
|
+
collection,
|
241
242
|
index
|
242
243
|
);
|
243
|
-
|
244
|
+
|
244
245
|
if (success) {
|
245
|
-
|
246
|
-
|
246
|
+
MessageFormatter.success(`Successfully created index: ${index.key} (type: ${index.type})`);
|
247
|
+
|
247
248
|
// Add delay between successful indexes
|
248
249
|
await delay(1000);
|
249
250
|
} else {
|
250
|
-
|
251
|
+
MessageFormatter.error(`Failed to create index: ${index.key} (type: ${index.type}), will retry in next round`);
|
251
252
|
indexesToProcess.push(index); // Add back to retry list
|
252
253
|
}
|
253
254
|
}
|
254
|
-
|
255
|
+
|
255
256
|
if (indexesToProcess.length === 0) {
|
256
|
-
|
257
|
+
MessageFormatter.success(`\nSuccessfully created all ${indexes.length} indexes for collection '${collectionId}'`);
|
257
258
|
return true;
|
258
259
|
}
|
259
|
-
|
260
|
+
|
260
261
|
overallRetryCount++;
|
261
|
-
|
262
|
+
|
262
263
|
if (overallRetryCount < maxOverallRetries) {
|
263
|
-
|
264
|
+
MessageFormatter.warning(`\nWaiting 5 seconds before retrying ${indexesToProcess.length} failed indexes...`);
|
264
265
|
await delay(5000);
|
265
266
|
}
|
266
267
|
}
|
267
|
-
|
268
|
+
|
268
269
|
// If we get here, some indexes still failed after all retries
|
269
270
|
if (indexesToProcess.length > 0) {
|
270
|
-
|
271
|
-
|
271
|
+
const failedIndexKeys = indexesToProcess.map(i => `${i.key} (${i.type})`).join(', ');
|
272
|
+
MessageFormatter.error(`\nFailed to create ${indexesToProcess.length} indexes after ${maxOverallRetries} attempts: ${failedIndexKeys}`);
|
273
|
+
MessageFormatter.error(`This may indicate a fundamental issue with the index definitions or Appwrite instance`);
|
272
274
|
return false;
|
273
275
|
}
|
274
|
-
|
275
|
-
|
276
|
+
|
277
|
+
MessageFormatter.success(`\nSuccessfully created all ${indexes.length} indexes for collection '${collectionId}'`);
|
276
278
|
return true;
|
277
279
|
};
|
278
280
|
|