appwrite-utils-cli 1.11.0 → 1.12.0

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.
Files changed (250) hide show
  1. package/{src/adapters/index.ts → dist/adapters/index.d.ts} +0 -1
  2. package/dist/adapters/index.js +10 -0
  3. package/dist/backups/operations/bucketBackup.d.ts +19 -0
  4. package/dist/backups/operations/bucketBackup.js +197 -0
  5. package/dist/backups/operations/collectionBackup.d.ts +30 -0
  6. package/dist/backups/operations/collectionBackup.js +201 -0
  7. package/dist/backups/operations/comprehensiveBackup.d.ts +25 -0
  8. package/dist/backups/operations/comprehensiveBackup.js +238 -0
  9. package/dist/backups/schemas/bucketManifest.d.ts +93 -0
  10. package/dist/backups/schemas/bucketManifest.js +33 -0
  11. package/dist/backups/schemas/comprehensiveManifest.d.ts +108 -0
  12. package/dist/backups/schemas/comprehensiveManifest.js +32 -0
  13. package/dist/backups/tracking/centralizedTracking.d.ts +34 -0
  14. package/dist/backups/tracking/centralizedTracking.js +274 -0
  15. package/dist/cli/commands/configCommands.d.ts +8 -0
  16. package/dist/cli/commands/configCommands.js +210 -0
  17. package/dist/cli/commands/databaseCommands.d.ts +14 -0
  18. package/dist/cli/commands/databaseCommands.js +696 -0
  19. package/dist/cli/commands/functionCommands.d.ts +7 -0
  20. package/dist/cli/commands/functionCommands.js +330 -0
  21. package/dist/cli/commands/importFileCommands.d.ts +7 -0
  22. package/dist/cli/commands/importFileCommands.js +674 -0
  23. package/dist/cli/commands/schemaCommands.d.ts +7 -0
  24. package/dist/cli/commands/schemaCommands.js +169 -0
  25. package/dist/cli/commands/storageCommands.d.ts +5 -0
  26. package/dist/cli/commands/storageCommands.js +142 -0
  27. package/dist/cli/commands/transferCommands.d.ts +5 -0
  28. package/dist/cli/commands/transferCommands.js +382 -0
  29. package/dist/collections/columns.d.ts +13 -0
  30. package/dist/collections/columns.js +1339 -0
  31. package/dist/collections/indexes.d.ts +12 -0
  32. package/dist/collections/indexes.js +215 -0
  33. package/dist/collections/methods.d.ts +19 -0
  34. package/dist/collections/methods.js +605 -0
  35. package/dist/collections/tableOperations.d.ts +87 -0
  36. package/dist/collections/tableOperations.js +466 -0
  37. package/dist/collections/transferOperations.d.ts +8 -0
  38. package/dist/collections/transferOperations.js +411 -0
  39. package/dist/collections/wipeOperations.d.ts +17 -0
  40. package/dist/collections/wipeOperations.js +306 -0
  41. package/dist/databases/methods.d.ts +6 -0
  42. package/dist/databases/methods.js +35 -0
  43. package/dist/databases/setup.d.ts +5 -0
  44. package/dist/databases/setup.js +45 -0
  45. package/dist/examples/yamlTerminologyExample.d.ts +42 -0
  46. package/dist/examples/yamlTerminologyExample.js +272 -0
  47. package/dist/functions/deployments.d.ts +4 -0
  48. package/dist/functions/deployments.js +146 -0
  49. package/dist/functions/fnConfigDiscovery.d.ts +3 -0
  50. package/dist/functions/fnConfigDiscovery.js +108 -0
  51. package/dist/functions/methods.d.ts +16 -0
  52. package/dist/functions/methods.js +174 -0
  53. package/dist/init.d.ts +2 -0
  54. package/dist/init.js +57 -0
  55. package/dist/interactiveCLI.d.ts +36 -0
  56. package/dist/interactiveCLI.js +952 -0
  57. package/dist/main.d.ts +2 -0
  58. package/dist/main.js +1125 -0
  59. package/dist/migrations/afterImportActions.d.ts +17 -0
  60. package/dist/migrations/afterImportActions.js +305 -0
  61. package/dist/migrations/appwriteToX.d.ts +211 -0
  62. package/dist/migrations/appwriteToX.js +493 -0
  63. package/dist/migrations/comprehensiveTransfer.d.ts +147 -0
  64. package/dist/migrations/comprehensiveTransfer.js +1315 -0
  65. package/dist/migrations/dataLoader.d.ts +755 -0
  66. package/dist/migrations/dataLoader.js +1272 -0
  67. package/dist/migrations/importController.d.ts +25 -0
  68. package/dist/migrations/importController.js +283 -0
  69. package/dist/migrations/importDataActions.d.ts +50 -0
  70. package/dist/migrations/importDataActions.js +230 -0
  71. package/dist/migrations/relationships.d.ts +29 -0
  72. package/dist/migrations/relationships.js +203 -0
  73. package/dist/migrations/services/DataTransformationService.d.ts +55 -0
  74. package/dist/migrations/services/DataTransformationService.js +158 -0
  75. package/dist/migrations/services/FileHandlerService.d.ts +75 -0
  76. package/dist/migrations/services/FileHandlerService.js +236 -0
  77. package/dist/migrations/services/ImportOrchestrator.d.ts +99 -0
  78. package/dist/migrations/services/ImportOrchestrator.js +493 -0
  79. package/dist/migrations/services/RateLimitManager.d.ts +138 -0
  80. package/dist/migrations/services/RateLimitManager.js +279 -0
  81. package/dist/migrations/services/RelationshipResolver.d.ts +120 -0
  82. package/dist/migrations/services/RelationshipResolver.js +332 -0
  83. package/dist/migrations/services/UserMappingService.d.ts +109 -0
  84. package/dist/migrations/services/UserMappingService.js +277 -0
  85. package/dist/migrations/services/ValidationService.d.ts +74 -0
  86. package/dist/migrations/services/ValidationService.js +260 -0
  87. package/dist/migrations/transfer.d.ts +30 -0
  88. package/dist/migrations/transfer.js +661 -0
  89. package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +131 -0
  90. package/dist/migrations/yaml/YamlImportConfigLoader.js +383 -0
  91. package/dist/migrations/yaml/YamlImportIntegration.d.ts +93 -0
  92. package/dist/migrations/yaml/YamlImportIntegration.js +341 -0
  93. package/dist/migrations/yaml/generateImportSchemas.d.ts +30 -0
  94. package/dist/migrations/yaml/generateImportSchemas.js +1327 -0
  95. package/dist/schemas/authUser.d.ts +24 -0
  96. package/dist/schemas/authUser.js +17 -0
  97. package/dist/setup.d.ts +2 -0
  98. package/{src/setup.ts → dist/setup.js} +0 -3
  99. package/dist/setupCommands.d.ts +58 -0
  100. package/dist/setupCommands.js +489 -0
  101. package/dist/setupController.d.ts +9 -0
  102. package/dist/setupController.js +34 -0
  103. package/dist/shared/backupMetadataSchema.d.ts +94 -0
  104. package/dist/shared/backupMetadataSchema.js +38 -0
  105. package/dist/shared/backupTracking.d.ts +18 -0
  106. package/dist/shared/backupTracking.js +176 -0
  107. package/dist/shared/confirmationDialogs.d.ts +75 -0
  108. package/dist/shared/confirmationDialogs.js +236 -0
  109. package/dist/shared/migrationHelpers.d.ts +61 -0
  110. package/dist/shared/migrationHelpers.js +145 -0
  111. package/{src/shared/operationLogger.ts → dist/shared/operationLogger.d.ts} +1 -11
  112. package/dist/shared/operationLogger.js +12 -0
  113. package/dist/shared/operationQueue.d.ts +40 -0
  114. package/dist/shared/operationQueue.js +310 -0
  115. package/dist/shared/operationsTable.d.ts +26 -0
  116. package/dist/shared/operationsTable.js +287 -0
  117. package/dist/shared/operationsTableSchema.d.ts +48 -0
  118. package/dist/shared/operationsTableSchema.js +35 -0
  119. package/dist/shared/progressManager.d.ts +62 -0
  120. package/dist/shared/progressManager.js +215 -0
  121. package/dist/shared/relationshipExtractor.d.ts +56 -0
  122. package/dist/shared/relationshipExtractor.js +138 -0
  123. package/dist/shared/selectionDialogs.d.ts +220 -0
  124. package/dist/shared/selectionDialogs.js +588 -0
  125. package/dist/storage/backupCompression.d.ts +20 -0
  126. package/dist/storage/backupCompression.js +67 -0
  127. package/dist/storage/methods.d.ts +44 -0
  128. package/dist/storage/methods.js +475 -0
  129. package/dist/storage/schemas.d.ts +842 -0
  130. package/dist/storage/schemas.js +175 -0
  131. package/dist/tables/indexManager.d.ts +65 -0
  132. package/dist/tables/indexManager.js +294 -0
  133. package/{src/types.ts → dist/types.d.ts} +1 -6
  134. package/dist/types.js +3 -0
  135. package/dist/users/methods.d.ts +16 -0
  136. package/dist/users/methods.js +276 -0
  137. package/dist/utils/configMigration.d.ts +1 -0
  138. package/dist/utils/configMigration.js +261 -0
  139. package/dist/utils/index.js +2 -0
  140. package/dist/utils/loadConfigs.d.ts +50 -0
  141. package/dist/utils/loadConfigs.js +357 -0
  142. package/dist/utils/setupFiles.d.ts +4 -0
  143. package/dist/utils/setupFiles.js +1190 -0
  144. package/dist/utilsController.d.ts +114 -0
  145. package/dist/utilsController.js +898 -0
  146. package/package.json +6 -3
  147. package/CHANGELOG.md +0 -35
  148. package/CONFIG_TODO.md +0 -1189
  149. package/SELECTION_DIALOGS.md +0 -146
  150. package/SERVICE_IMPLEMENTATION_REPORT.md +0 -462
  151. package/scripts/copy-templates.ts +0 -23
  152. package/src/backups/operations/bucketBackup.ts +0 -277
  153. package/src/backups/operations/collectionBackup.ts +0 -310
  154. package/src/backups/operations/comprehensiveBackup.ts +0 -342
  155. package/src/backups/schemas/bucketManifest.ts +0 -78
  156. package/src/backups/schemas/comprehensiveManifest.ts +0 -76
  157. package/src/backups/tracking/centralizedTracking.ts +0 -352
  158. package/src/cli/commands/configCommands.ts +0 -265
  159. package/src/cli/commands/databaseCommands.ts +0 -931
  160. package/src/cli/commands/functionCommands.ts +0 -419
  161. package/src/cli/commands/importFileCommands.ts +0 -815
  162. package/src/cli/commands/schemaCommands.ts +0 -200
  163. package/src/cli/commands/storageCommands.ts +0 -151
  164. package/src/cli/commands/transferCommands.ts +0 -454
  165. package/src/collections/attributes.ts.backup +0 -1555
  166. package/src/collections/columns.ts +0 -2025
  167. package/src/collections/indexes.ts +0 -350
  168. package/src/collections/methods.ts +0 -714
  169. package/src/collections/tableOperations.ts +0 -542
  170. package/src/collections/transferOperations.ts +0 -589
  171. package/src/collections/wipeOperations.ts +0 -449
  172. package/src/databases/methods.ts +0 -49
  173. package/src/databases/setup.ts +0 -77
  174. package/src/examples/yamlTerminologyExample.ts +0 -346
  175. package/src/functions/deployments.ts +0 -221
  176. package/src/functions/fnConfigDiscovery.ts +0 -103
  177. package/src/functions/methods.ts +0 -284
  178. package/src/init.ts +0 -62
  179. package/src/interactiveCLI.ts +0 -1201
  180. package/src/main.ts +0 -1517
  181. package/src/migrations/afterImportActions.ts +0 -579
  182. package/src/migrations/appwriteToX.ts +0 -668
  183. package/src/migrations/comprehensiveTransfer.ts +0 -2285
  184. package/src/migrations/dataLoader.ts +0 -1729
  185. package/src/migrations/importController.ts +0 -440
  186. package/src/migrations/importDataActions.ts +0 -315
  187. package/src/migrations/relationships.ts +0 -333
  188. package/src/migrations/services/DataTransformationService.ts +0 -196
  189. package/src/migrations/services/FileHandlerService.ts +0 -311
  190. package/src/migrations/services/ImportOrchestrator.ts +0 -675
  191. package/src/migrations/services/RateLimitManager.ts +0 -363
  192. package/src/migrations/services/RelationshipResolver.ts +0 -461
  193. package/src/migrations/services/UserMappingService.ts +0 -345
  194. package/src/migrations/services/ValidationService.ts +0 -349
  195. package/src/migrations/transfer.ts +0 -1113
  196. package/src/migrations/yaml/YamlImportConfigLoader.ts +0 -439
  197. package/src/migrations/yaml/YamlImportIntegration.ts +0 -446
  198. package/src/migrations/yaml/generateImportSchemas.ts +0 -1354
  199. package/src/schemas/authUser.ts +0 -23
  200. package/src/setupCommands.ts +0 -602
  201. package/src/setupController.ts +0 -43
  202. package/src/shared/backupMetadataSchema.ts +0 -93
  203. package/src/shared/backupTracking.ts +0 -211
  204. package/src/shared/confirmationDialogs.ts +0 -327
  205. package/src/shared/migrationHelpers.ts +0 -232
  206. package/src/shared/operationQueue.ts +0 -376
  207. package/src/shared/operationsTable.ts +0 -338
  208. package/src/shared/operationsTableSchema.ts +0 -60
  209. package/src/shared/progressManager.ts +0 -278
  210. package/src/shared/relationshipExtractor.ts +0 -214
  211. package/src/shared/selectionDialogs.ts +0 -802
  212. package/src/storage/backupCompression.ts +0 -88
  213. package/src/storage/methods.ts +0 -711
  214. package/src/storage/schemas.ts +0 -205
  215. package/src/tables/indexManager.ts +0 -409
  216. package/src/types/node-appwrite-tablesdb.d.ts +0 -44
  217. package/src/users/methods.ts +0 -358
  218. package/src/utils/configMigration.ts +0 -348
  219. package/src/utils/loadConfigs.ts +0 -457
  220. package/src/utils/setupFiles.ts +0 -1236
  221. package/src/utilsController.ts +0 -1263
  222. package/tests/README.md +0 -497
  223. package/tests/adapters/AdapterFactory.test.ts +0 -277
  224. package/tests/integration/syncOperations.test.ts +0 -463
  225. package/tests/jest.config.js +0 -25
  226. package/tests/migration/configMigration.test.ts +0 -546
  227. package/tests/setup.ts +0 -62
  228. package/tests/testUtils.ts +0 -340
  229. package/tests/utils/loadConfigs.test.ts +0 -350
  230. package/tests/validation/configValidation.test.ts +0 -412
  231. package/tsconfig.json +0 -44
  232. /package/{src → dist}/functions/templates/count-docs-in-collection/README.md +0 -0
  233. /package/{src → dist}/functions/templates/count-docs-in-collection/src/main.ts +0 -0
  234. /package/{src → dist}/functions/templates/count-docs-in-collection/src/request.ts +0 -0
  235. /package/{src → dist}/functions/templates/hono-typescript/README.md +0 -0
  236. /package/{src → dist}/functions/templates/hono-typescript/src/adapters/request.ts +0 -0
  237. /package/{src → dist}/functions/templates/hono-typescript/src/adapters/response.ts +0 -0
  238. /package/{src → dist}/functions/templates/hono-typescript/src/app.ts +0 -0
  239. /package/{src → dist}/functions/templates/hono-typescript/src/context.ts +0 -0
  240. /package/{src → dist}/functions/templates/hono-typescript/src/main.ts +0 -0
  241. /package/{src → dist}/functions/templates/hono-typescript/src/middleware/appwrite.ts +0 -0
  242. /package/{src → dist}/functions/templates/typescript-node/README.md +0 -0
  243. /package/{src → dist}/functions/templates/typescript-node/src/context.ts +0 -0
  244. /package/{src → dist}/functions/templates/typescript-node/src/main.ts +0 -0
  245. /package/{src → dist}/functions/templates/uv/README.md +0 -0
  246. /package/{src → dist}/functions/templates/uv/pyproject.toml +0 -0
  247. /package/{src → dist}/functions/templates/uv/src/__init__.py +0 -0
  248. /package/{src → dist}/functions/templates/uv/src/context.py +0 -0
  249. /package/{src → dist}/functions/templates/uv/src/main.py +0 -0
  250. /package/{src/utils/index.ts → dist/utils/index.d.ts} +0 -0
@@ -1,350 +0,0 @@
1
- import { indexSchema, type Index } from "appwrite-utils";
2
- import { Databases, IndexType, Query, type Models } from "node-appwrite";
3
- import type { DatabaseAdapter } from "appwrite-utils-helpers";
4
- import { delay, tryAwaitWithRetry, calculateExponentialBackoff, isLegacyDatabases, MessageFormatter } from "appwrite-utils-helpers";
5
-
6
- // System attributes that are always available for indexing in Appwrite
7
- const SYSTEM_ATTRIBUTES = ['$id', '$createdAt', '$updatedAt', '$permissions'];
8
-
9
- // Interface for index with status
10
- interface IndexWithStatus {
11
- key: string;
12
- type: string;
13
- status: 'available' | 'processing' | 'deleting' | 'stuck' | 'failed';
14
- error: string;
15
- attributes: string[];
16
- orders?: string[];
17
- $createdAt: string;
18
- $updatedAt: string;
19
- }
20
-
21
- /**
22
- * Wait for index to become available, with retry logic for stuck indexes and exponential backoff
23
- */
24
- const waitForIndexAvailable = async (
25
- db: Databases | DatabaseAdapter,
26
- dbId: string,
27
- collectionId: string,
28
- indexKey: string,
29
- maxWaitTime: number = 60000, // 1 minute
30
- retryCount: number = 0,
31
- maxRetries: number = 5
32
- ): Promise<boolean> => {
33
- const startTime = Date.now();
34
- let checkInterval = 2000; // Start with 2 seconds
35
-
36
- // Calculate exponential backoff: 2s, 4s, 8s, 16s, 30s (capped at 30s)
37
- if (retryCount > 0) {
38
- const exponentialDelay = calculateExponentialBackoff(retryCount);
39
- await delay(exponentialDelay);
40
- }
41
-
42
- while (Date.now() - startTime < maxWaitTime) {
43
- try {
44
- const indexList = await (isLegacyDatabases(db)
45
- ? db.listIndexes(dbId, collectionId)
46
- : (db as DatabaseAdapter).listIndexes({ databaseId: dbId, tableId: collectionId }));
47
- const indexes: any[] = isLegacyDatabases(db)
48
- ? (indexList as any).indexes
49
- : ((indexList as any).data || (indexList as any).indexes || []);
50
- const index = indexes.find((idx: any) => idx.key === indexKey) as IndexWithStatus | undefined;
51
-
52
- if (!index) {
53
- MessageFormatter.error(`Index '${indexKey}' not found in database '${dbId}' collection '${collectionId}'`);
54
- return false;
55
- }
56
-
57
- switch (index.status) {
58
- case 'available':
59
- return true;
60
-
61
- case 'failed':
62
- MessageFormatter.error(`Index '${indexKey}' failed: ${index.error} (type: ${index.type}, attributes: [${index.attributes.join(', ')}])`);
63
- return false;
64
-
65
- case 'stuck':
66
- MessageFormatter.warning(`Index '${indexKey}' is stuck, will retry... (type: ${index.type}, attributes: [${index.attributes.join(', ')}])`);
67
- return false;
68
-
69
- case 'processing':
70
- // Continue waiting
71
- break;
72
-
73
- case 'deleting':
74
- MessageFormatter.warning(`Index '${indexKey}' is being deleted`);
75
- break;
76
-
77
- default:
78
- MessageFormatter.warning(`Unknown status '${index.status}' for index '${indexKey}'`);
79
- break;
80
- }
81
-
82
- await delay(checkInterval);
83
- } catch (error) {
84
- MessageFormatter.error(`Error checking index '${indexKey}' status in database '${dbId}' collection '${collectionId}': ${error}`);
85
- return false;
86
- }
87
- }
88
-
89
- // Timeout reached
90
- MessageFormatter.warning(`Timeout waiting for index '${indexKey}' (${maxWaitTime}ms)`);
91
-
92
- // If we have retries left and this isn't the last retry, try recreating
93
- if (retryCount < maxRetries) {
94
- MessageFormatter.info(`Retrying index '${indexKey}' creation (attempt ${retryCount + 1}/${maxRetries})`);
95
- return false; // Signal that we need to retry
96
- }
97
-
98
- return false;
99
- };
100
-
101
-
102
- /**
103
- * Enhanced index creation with proper status monitoring and retry logic
104
- */
105
- export const createOrUpdateIndexWithStatusCheck = async (
106
- dbId: string,
107
- db: Databases,
108
- collectionId: string,
109
- collection: Models.Collection,
110
- index: Index,
111
- retryCount: number = 0,
112
- maxRetries: number = 3,
113
- ): Promise<boolean> => {
114
- MessageFormatter.info(`Creating/updating index '${index.key}' (attempt ${retryCount + 1}/${maxRetries + 1}) - type: ${index.type}, attributes: [${index.attributes.join(', ')}]`);
115
-
116
- try {
117
- // First, validate that all required attributes exist
118
- const freshCollection = await db.getCollection(dbId, collectionId);
119
- const existingAttributeKeys = freshCollection.attributes.map((attr: any) => attr.key);
120
-
121
- // Include system attributes that are always available
122
- const allAvailableAttributes = [...existingAttributeKeys, ...SYSTEM_ATTRIBUTES];
123
-
124
- const missingAttributes = index.attributes.filter(attr => !allAvailableAttributes.includes(attr));
125
-
126
- if (missingAttributes.length > 0) {
127
- MessageFormatter.error(`Index '${index.key}' cannot be created: missing attributes [${missingAttributes.join(', ')}] (type: ${index.type})`);
128
- MessageFormatter.error(`Available attributes: [${existingAttributeKeys.join(', ')}, ${SYSTEM_ATTRIBUTES.join(', ')}]`);
129
- return false; // Don't retry if attributes are missing
130
- }
131
-
132
- // Try to create/update the index using existing logic
133
- await createOrUpdateIndex(dbId, db, collectionId, index);
134
-
135
- // Now wait for the index to become available
136
- const success = await waitForIndexAvailable(
137
- db,
138
- dbId,
139
- collectionId,
140
- index.key,
141
- 60000, // 1 minute timeout
142
- retryCount,
143
- maxRetries
144
- );
145
-
146
- if (success) {
147
- return true;
148
- }
149
-
150
- // If not successful and we have retries left, just retry the index creation
151
- if (retryCount < maxRetries) {
152
- MessageFormatter.warning(`Index '${index.key}' failed/stuck, retrying (${retryCount + 1}/${maxRetries}) - type: ${index.type}, attributes: [${index.attributes.join(', ')}]`);
153
-
154
- // Wait a bit before retry
155
- await new Promise(resolve => setTimeout(resolve, 2000 * (retryCount + 1)));
156
-
157
- // Retry the index creation
158
- return await createOrUpdateIndexWithStatusCheck(
159
- dbId,
160
- db,
161
- collectionId,
162
- collection,
163
- index,
164
- retryCount + 1,
165
- maxRetries
166
- );
167
- }
168
-
169
- MessageFormatter.error(`Failed to create index '${index.key}' after ${maxRetries + 1} attempts (type: ${index.type}, attributes: [${index.attributes.join(', ')}])`);
170
- return false;
171
-
172
- } catch (error) {
173
- const errorMessage = error instanceof Error ? error.message : String(error);
174
- MessageFormatter.error(`Error creating index '${index.key}': ${errorMessage} (type: ${index.type}, attributes: [${index.attributes.join(', ')}])`);
175
-
176
- // Check if this is a permanent error that shouldn't be retried
177
- if (errorMessage.toLowerCase().includes('not found') ||
178
- errorMessage.toLowerCase().includes('missing') ||
179
- errorMessage.toLowerCase().includes('does not exist') ||
180
- errorMessage.toLowerCase().includes('attribute') && errorMessage.toLowerCase().includes('not found')) {
181
- MessageFormatter.error(`Index '${index.key}' has permanent error - not retrying (type: ${index.type})`);
182
- return false;
183
- }
184
-
185
- if (retryCount < maxRetries) {
186
- MessageFormatter.warning(`Retrying index '${index.key}' due to error... (type: ${index.type}, attributes: [${index.attributes.join(', ')}])`);
187
-
188
- // Wait a bit before retry
189
- await delay(2000);
190
-
191
- return await createOrUpdateIndexWithStatusCheck(
192
- dbId,
193
- db,
194
- collectionId,
195
- collection,
196
- index,
197
- retryCount + 1,
198
- maxRetries
199
- );
200
- }
201
-
202
- return false;
203
- }
204
- };
205
-
206
- /**
207
- * Enhanced index creation with status monitoring for all indexes
208
- */
209
- export const createOrUpdateIndexesWithStatusCheck = async (
210
- dbId: string,
211
- db: Databases,
212
- collectionId: string,
213
- collection: Models.Collection,
214
- indexes: Index[]
215
- ): Promise<boolean> => {
216
- MessageFormatter.info(`Creating/updating ${indexes.length} indexes with status monitoring for collection '${collectionId}'`);
217
-
218
- let indexesToProcess = [...indexes];
219
- let overallRetryCount = 0;
220
- const maxOverallRetries = 3;
221
-
222
- while (indexesToProcess.length > 0 && overallRetryCount < maxOverallRetries) {
223
- const remainingIndexes = [...indexesToProcess];
224
- indexesToProcess = []; // Reset for next iteration
225
-
226
- for (const index of remainingIndexes) {
227
- const success = await createOrUpdateIndexWithStatusCheck(
228
- dbId,
229
- db,
230
- collectionId,
231
- collection,
232
- index
233
- );
234
-
235
- if (success) {
236
- MessageFormatter.info(`✅ ${index.key} (${index.type})`);
237
-
238
- // Add delay between successful indexes
239
- await delay(1000);
240
- } else {
241
- MessageFormatter.info(`❌ ${index.key} (${index.type})`);
242
- indexesToProcess.push(index); // Add back to retry list
243
- }
244
- }
245
-
246
- if (indexesToProcess.length === 0) {
247
- return true;
248
- }
249
-
250
- overallRetryCount++;
251
-
252
- if (overallRetryCount < maxOverallRetries) {
253
- MessageFormatter.warning(`⏳ Retrying ${indexesToProcess.length} failed indexes...`);
254
- await delay(5000);
255
- }
256
- }
257
-
258
- // If we get here, some indexes still failed after all retries
259
- if (indexesToProcess.length > 0) {
260
- const failedIndexKeys = indexesToProcess.map(i => `${i.key} (${i.type})`).join(', ');
261
- MessageFormatter.error(`\nFailed to create ${indexesToProcess.length} indexes after ${maxOverallRetries} attempts: ${failedIndexKeys}`);
262
- MessageFormatter.error(`This may indicate a fundamental issue with the index definitions or Appwrite instance`);
263
- return false;
264
- }
265
-
266
- MessageFormatter.success(`\nSuccessfully created all ${indexes.length} indexes for collection '${collectionId}'`);
267
- return true;
268
- };
269
-
270
- export const createOrUpdateIndex = async (
271
- dbId: string,
272
- db: Databases,
273
- collectionId: string,
274
- index: Index
275
- ) => {
276
- const existingIndex = await db.listIndexes(dbId, collectionId, [
277
- Query.equal("key", index.key),
278
- ]);
279
-
280
- let createIndex = false;
281
- let newIndex: Models.Index | null = null;
282
-
283
- if (existingIndex.total === 0) {
284
- // No existing index, create it
285
- createIndex = true;
286
- } else {
287
- const existing = existingIndex.indexes[0];
288
-
289
- // Check key and type
290
- const keyMatches = existing.key === index.key;
291
- const typeMatches = existing.type === index.type;
292
-
293
- // Compare attributes as SETS (order doesn't matter, only content)
294
- const existingAttrsSet = new Set(existing.attributes);
295
- const newAttrsSet = new Set(index.attributes);
296
- const attributesMatch =
297
- existingAttrsSet.size === newAttrsSet.size &&
298
- [...existingAttrsSet].every(attr => newAttrsSet.has(attr));
299
-
300
- // Compare orders as SETS if both exist (order doesn't matter)
301
- let ordersMatch = true;
302
- if (index.orders && existing.orders) {
303
- const existingOrdersSet = new Set(existing.orders);
304
- const newOrdersSet = new Set(index.orders);
305
- ordersMatch =
306
- existingOrdersSet.size === newOrdersSet.size &&
307
- [...existingOrdersSet].every(ord => newOrdersSet.has(ord));
308
- }
309
-
310
- // Only recreate if something genuinely changed
311
- if (!keyMatches || !typeMatches || !attributesMatch || !ordersMatch) {
312
- await db.deleteIndex(dbId, collectionId, existing.key);
313
- createIndex = true;
314
- }
315
- }
316
-
317
- if (createIndex) {
318
- // Ensure orders array exists and matches attributes length
319
- // Default to "asc" for each attribute if not specified
320
- const orders = index.orders && index.orders.length === index.attributes.length
321
- ? index.orders
322
- : index.attributes.map(() => "asc");
323
-
324
- newIndex = await db.createIndex(
325
- dbId,
326
- collectionId,
327
- index.key,
328
- index.type as IndexType,
329
- index.attributes,
330
- orders
331
- );
332
- }
333
-
334
- return newIndex;
335
- };
336
-
337
- export const createOrUpdateIndexes = async (
338
- dbId: string,
339
- db: Databases,
340
- collectionId: string,
341
- indexes: Index[]
342
- ) => {
343
- for (const index of indexes) {
344
- await tryAwaitWithRetry(
345
- async () => await createOrUpdateIndex(dbId, db, collectionId, index)
346
- );
347
- // Add delay after each index creation/update
348
- await delay(500);
349
- }
350
- };