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,457 +0,0 @@
1
- import path from "path";
2
- import fs from "fs";
3
- import { type AppwriteConfig, type Collection, type CollectionCreate, type Table, type TableCreate } from "appwrite-utils";
4
- import { register } from "tsx/esm/api"; // Import the register function
5
- import { pathToFileURL } from "node:url";
6
- import chalk from "chalk";
7
- import {
8
- findYamlConfig,
9
- loadYamlConfig,
10
- loadYamlConfigWithSession,
11
- extractSessionOptionsFromConfig,
12
- validateCollectionsTablesConfig,
13
- reportValidationResults,
14
- type YamlSessionOptions,
15
- type ValidationResult
16
- } from "appwrite-utils-helpers";
17
- import { detectAppwriteVersionCached, fetchServerVersion, isVersionAtLeast } from 'appwrite-utils-helpers';
18
- import { MessageFormatter } from "appwrite-utils-helpers";
19
- import { resolveCollectionsDir, resolveTablesDir } from 'appwrite-utils-helpers';
20
- import {
21
- findAppwriteConfig,
22
- findAppwriteConfigTS,
23
- findFunctionsDir,
24
- discoverCollections,
25
- discoverTables,
26
- discoverLegacyDirectory
27
- } from 'appwrite-utils-helpers';
28
-
29
- /**
30
- * Session authentication preservation options for config loading
31
- */
32
- export interface SessionPreservationOptions {
33
- sessionCookie?: string;
34
- authMethod?: "session" | "apikey" | "auto";
35
- sessionMetadata?: {
36
- email?: string;
37
- expiresAt?: string;
38
- };
39
- }
40
-
41
- /**
42
- * Configuration loading options
43
- */
44
- export interface ConfigLoadingOptions {
45
- validate?: boolean;
46
- strictMode?: boolean;
47
- reportValidation?: boolean;
48
- preserveAuth?: SessionPreservationOptions;
49
- }
50
-
51
- /**
52
- * Helper function to create session preservation options from session data
53
- * @param sessionCookie The session cookie string
54
- * @param email Optional email associated with the session
55
- * @param expiresAt Optional expiration timestamp
56
- * @returns SessionPreservationOptions object
57
- */
58
- export function createSessionPreservation(
59
- sessionCookie: string,
60
- email?: string,
61
- expiresAt?: string
62
- ): SessionPreservationOptions {
63
- return {
64
- sessionCookie,
65
- authMethod: "session",
66
- sessionMetadata: {
67
- ...(email && { email }),
68
- ...(expiresAt && { expiresAt })
69
- }
70
- };
71
- }
72
-
73
- // Re-export config discovery functions for backward compatibility
74
- export { findAppwriteConfig, findFunctionsDir } from 'appwrite-utils-helpers';
75
-
76
- /**
77
- * Loads the Appwrite configuration and returns both config and the path where it was found.
78
- * @param configDir The directory to search for config files.
79
- * @param options Loading options including validation settings and session preservation.
80
- * @returns Object containing the config, path, and validation results.
81
- */
82
- export const loadConfigWithPath = async (
83
- configDir: string,
84
- options: ConfigLoadingOptions = {}
85
- ): Promise<{
86
- config: AppwriteConfig;
87
- actualConfigPath: string;
88
- validation?: ValidationResult;
89
- }> => {
90
- const { validate = true, strictMode = false, reportValidation = true } = options;
91
- let config: AppwriteConfig | null = null;
92
- let actualConfigPath: string | null = null;
93
-
94
- // Convert session preservation options to YAML format
95
- const yamlSessionOptions: YamlSessionOptions | undefined = options.preserveAuth ? {
96
- sessionCookie: options.preserveAuth.sessionCookie,
97
- authMethod: options.preserveAuth.authMethod,
98
- sessionMetadata: options.preserveAuth.sessionMetadata,
99
- } : undefined;
100
-
101
- // Check if we're given the .appwrite directory directly
102
- if (configDir.endsWith('.appwrite')) {
103
- // Look for config files directly in this directory
104
- const possibleYamlFiles = ['config.yaml', 'config.yml', 'appwriteConfig.yaml', 'appwriteConfig.yml'];
105
- for (const fileName of possibleYamlFiles) {
106
- const yamlPath = path.join(configDir, fileName);
107
- if (fs.existsSync(yamlPath)) {
108
- config = yamlSessionOptions
109
- ? await loadYamlConfigWithSession(yamlPath, yamlSessionOptions)
110
- : await loadYamlConfig(yamlPath);
111
- actualConfigPath = yamlPath;
112
- break;
113
- }
114
- }
115
- } else {
116
- // Original logic: search for .appwrite directories
117
- const yamlConfigPath = findYamlConfig(configDir);
118
- if (yamlConfigPath) {
119
- config = yamlSessionOptions
120
- ? await loadYamlConfigWithSession(yamlConfigPath, yamlSessionOptions)
121
- : await loadYamlConfig(yamlConfigPath);
122
- actualConfigPath = yamlConfigPath;
123
- }
124
- }
125
-
126
- // Fall back to TypeScript config if YAML not found or failed to load
127
- if (!config) {
128
- const configPath = path.join(configDir, "appwriteConfig.ts");
129
-
130
- // Only try to load TypeScript config if the file exists
131
- if (fs.existsSync(configPath)) {
132
- const unregister = register(); // Register tsx enhancement
133
-
134
- try {
135
- const configUrl = pathToFileURL(configPath).href;
136
- const configModule = (await import(configUrl));
137
- config = configModule.default?.default || configModule.default || configModule;
138
- if (!config) {
139
- throw new Error("Failed to load config");
140
- }
141
- actualConfigPath = configPath;
142
- } finally {
143
- unregister(); // Unregister tsx when done
144
- }
145
- }
146
- }
147
-
148
- if (!config || !actualConfigPath) {
149
- throw new Error("No valid configuration found");
150
- }
151
-
152
- // Preserve session authentication if provided
153
- // This allows maintaining session context when config is reloaded during CLI operations
154
- if (options.preserveAuth) {
155
- const { sessionCookie, authMethod, sessionMetadata } = options.preserveAuth;
156
-
157
- // Inject session cookie into the loaded config
158
- if (sessionCookie) {
159
- config.sessionCookie = sessionCookie;
160
- }
161
-
162
- // Set or override authentication method preference
163
- if (authMethod) {
164
- config.authMethod = authMethod;
165
- }
166
-
167
- // Merge session metadata (email, expiration, etc.) with existing metadata
168
- if (sessionMetadata) {
169
- config.sessionMetadata = {
170
- ...config.sessionMetadata,
171
- ...sessionMetadata
172
- };
173
- }
174
-
175
- // Auto-detect authentication method if not explicitly provided
176
- // If we have a session cookie but no auth method specified, prefer session auth
177
- if (!authMethod && sessionCookie) {
178
- config.authMethod = "session";
179
- }
180
- }
181
-
182
- // Enhanced dual folder support: Load from BOTH collections/ AND tables/ directories
183
- const configFileDir = path.dirname(actualConfigPath);
184
- // Look for collections/tables directories in the same directory as the config file
185
- const collectionsDir = resolveCollectionsDir(configFileDir);
186
- const tablesDir = resolveTablesDir(configFileDir);
187
-
188
- // Initialize collections array
189
- config.collections = [];
190
-
191
- // Load from collections/ directory first (higher priority)
192
- const collectionsResult = await discoverCollections(collectionsDir);
193
- config.collections.push(...collectionsResult.collections);
194
-
195
- // Load from tables/ directory second (lower priority, check for conflicts)
196
- const tablesResult = await discoverTables(tablesDir, collectionsResult.loadedNames);
197
- config.collections.push(...tablesResult.tables);
198
-
199
- // Combine conflicts from both discovery operations
200
- const allConflicts = [...collectionsResult.conflicts, ...tablesResult.conflicts];
201
-
202
- // Report conflicts if any
203
- if (allConflicts.length > 0) {
204
- MessageFormatter.warning(`Found ${allConflicts.length} naming conflicts between collections/ and tables/`, { prefix: "Config" });
205
- allConflicts.forEach(conflict => {
206
- MessageFormatter.info(` - '${conflict.name}': ${conflict.source1} (used) vs ${conflict.source2} (skipped)`, { prefix: "Config" });
207
- });
208
- }
209
-
210
- // Fallback: If neither directory exists, try legacy single-directory detection
211
- if (!fs.existsSync(collectionsDir) && !fs.existsSync(tablesDir)) {
212
- // Determine directory (collections or tables) based on server version / API mode
213
- let dirName: 'collections' | 'tables' = "collections";
214
- try {
215
- const det = await detectAppwriteVersionCached(config.appwriteEndpoint, config.appwriteProject, config.appwriteKey);
216
- if (det.apiMode === 'tablesdb' || isVersionAtLeast(det.serverVersion, '1.8.0')) {
217
- dirName = 'tables';
218
- } else {
219
- // Try health version if not provided
220
- const ver = await fetchServerVersion(config.appwriteEndpoint);
221
- if (isVersionAtLeast(ver || undefined, '1.8.0')) dirName = 'tables';
222
- }
223
- } catch {}
224
-
225
- const legacyItems = await discoverLegacyDirectory(configFileDir, dirName);
226
- config.collections.push(...legacyItems);
227
- }
228
-
229
- // Ensure array exists even if empty
230
- config.collections = config.collections || [];
231
-
232
- // Log the final result
233
- const allCollections = config.collections || [];
234
- const fromCollectionsDir = allCollections.filter((c: any) => !c._isFromTablesDir).length;
235
- const fromTablesDir = allCollections.filter((c: any) => c._isFromTablesDir).length;
236
- const totalLoaded = allCollections.length;
237
-
238
- if (totalLoaded > 0) {
239
- if (fromTablesDir > 0) {
240
- MessageFormatter.success(`Successfully loaded ${totalLoaded} items total: ${fromCollectionsDir} from collections/ and ${fromTablesDir} from tables/`, { prefix: "Config" });
241
- } else {
242
- MessageFormatter.success(`Successfully loaded ${totalLoaded} collections from collections/`, { prefix: "Config" });
243
- }
244
- }
245
-
246
- // Validate configuration if requested
247
- let validation: ValidationResult | undefined;
248
- if (validate) {
249
- validation = validateCollectionsTablesConfig(config);
250
-
251
- // In strict mode, treat warnings as errors
252
- if (strictMode && validation.warnings.length > 0) {
253
- const strictValidation = {
254
- ...validation,
255
- isValid: false,
256
- errors: [...validation.errors, ...validation.warnings.map(w => ({ ...w, severity: "error" as const }))],
257
- warnings: []
258
- };
259
- validation = strictValidation;
260
- }
261
-
262
- // Report validation results if requested
263
- if (reportValidation) {
264
- reportValidationResults(validation, { verbose: true });
265
- }
266
-
267
- // Throw error if validation fails in strict mode
268
- if (strictMode && !validation.isValid) {
269
- throw new Error(`Configuration validation failed in strict mode. Found ${validation.errors.length} validation errors.`);
270
- }
271
- }
272
-
273
- return { config, actualConfigPath, validation };
274
- };
275
-
276
- /**
277
- * Loads the Appwrite configuration and all collection configurations from a specified directory.
278
- * Supports both YAML and TypeScript config formats with backward compatibility.
279
- * @param configDir The directory containing the config file and collections folder.
280
- * @param options Loading options including validation settings and session preservation.
281
- * @returns The loaded Appwrite configuration including collections.
282
- */
283
- export const loadConfig = async (
284
- configDir: string,
285
- options: ConfigLoadingOptions = {}
286
- ): Promise<AppwriteConfig> => {
287
- const { validate = false, strictMode = false, reportValidation = false } = options;
288
- let config: AppwriteConfig | null = null;
289
- let actualConfigPath: string | null = null;
290
-
291
- // Convert session preservation options to YAML format
292
- const yamlSessionOptions: YamlSessionOptions | undefined = options.preserveAuth ? {
293
- sessionCookie: options.preserveAuth.sessionCookie,
294
- authMethod: options.preserveAuth.authMethod,
295
- sessionMetadata: options.preserveAuth.sessionMetadata,
296
- } : undefined;
297
-
298
- // First try to find and load YAML config
299
- const yamlConfigPath = findYamlConfig(configDir);
300
- if (yamlConfigPath) {
301
- config = yamlSessionOptions
302
- ? await loadYamlConfigWithSession(yamlConfigPath, yamlSessionOptions)
303
- : await loadYamlConfig(yamlConfigPath);
304
- actualConfigPath = yamlConfigPath;
305
- }
306
-
307
- // Fall back to TypeScript config if YAML not found or failed to load
308
- if (!config) {
309
- const configPath = path.join(configDir, "appwriteConfig.ts");
310
-
311
- // Only try to load TypeScript config if the file exists
312
- if (fs.existsSync(configPath)) {
313
- const unregister = register(); // Register tsx enhancement
314
-
315
- try {
316
- const configUrl = pathToFileURL(configPath).href;
317
- const configModule = (await import(configUrl));
318
- config = configModule.default?.default || configModule.default || configModule;
319
- if (!config) {
320
- throw new Error("Failed to load config");
321
- }
322
- actualConfigPath = configPath;
323
- } finally {
324
- unregister(); // Unregister tsx when done
325
- }
326
- }
327
- }
328
-
329
- if (!config) {
330
- throw new Error("No valid configuration found");
331
- }
332
-
333
- // Preserve session authentication if provided
334
- // This allows maintaining session context when config is reloaded during CLI operations
335
- if (options.preserveAuth) {
336
- const { sessionCookie, authMethod, sessionMetadata } = options.preserveAuth;
337
-
338
- // Inject session cookie into the loaded config
339
- if (sessionCookie) {
340
- config.sessionCookie = sessionCookie;
341
- }
342
-
343
- // Set or override authentication method preference
344
- if (authMethod) {
345
- config.authMethod = authMethod;
346
- }
347
-
348
- // Merge session metadata (email, expiration, etc.) with existing metadata
349
- if (sessionMetadata) {
350
- config.sessionMetadata = {
351
- ...config.sessionMetadata,
352
- ...sessionMetadata
353
- };
354
- }
355
-
356
- // Auto-detect authentication method if not explicitly provided
357
- // If we have a session cookie but no auth method specified, prefer session auth
358
- if (!authMethod && sessionCookie) {
359
- config.authMethod = "session";
360
- }
361
- }
362
-
363
- // Enhanced dual folder support: Load from BOTH collections/ AND tables/ directories
364
- const configFileDir = actualConfigPath ? path.dirname(actualConfigPath) : configDir;
365
- // Look for collections/tables directories in the same directory as the config file
366
- const collectionsDir = resolveCollectionsDir(configFileDir);
367
- const tablesDir = resolveTablesDir(configFileDir);
368
-
369
- // Initialize collections array
370
- config.collections = [];
371
-
372
- // Load from collections/ directory first (higher priority)
373
- const collectionsResult = await discoverCollections(collectionsDir);
374
- config.collections.push(...collectionsResult.collections);
375
-
376
- // Load from tables/ directory second (lower priority, check for conflicts)
377
- const tablesResult = await discoverTables(tablesDir, collectionsResult.loadedNames);
378
- config.collections.push(...tablesResult.tables);
379
-
380
- // Combine conflicts from both discovery operations
381
- const allConflicts = [...collectionsResult.conflicts, ...tablesResult.conflicts];
382
-
383
- // Report conflicts if any
384
- if (allConflicts.length > 0) {
385
- MessageFormatter.warning(`Found ${allConflicts.length} naming conflicts between collections/ and tables/`, { prefix: "Config" });
386
- allConflicts.forEach(conflict => {
387
- MessageFormatter.info(` - '${conflict.name}': ${conflict.source1} (used) vs ${conflict.source2} (skipped)`, { prefix: "Config" });
388
- });
389
- }
390
-
391
- // Fallback: If neither directory exists, try legacy single-directory detection
392
- if (!fs.existsSync(collectionsDir) && !fs.existsSync(tablesDir)) {
393
- // Determine directory (collections or tables) based on server version / API mode
394
- let dirName: 'collections' | 'tables' = "collections";
395
- try {
396
- const det = await detectAppwriteVersionCached(config.appwriteEndpoint, config.appwriteProject, config.appwriteKey);
397
- if (det.apiMode === 'tablesdb' || isVersionAtLeast(det.serverVersion, '1.8.0')) {
398
- dirName = 'tables';
399
- } else {
400
- const ver = await fetchServerVersion(config.appwriteEndpoint);
401
- if (isVersionAtLeast(ver || undefined, '1.8.0')) dirName = 'tables';
402
- }
403
- } catch {}
404
-
405
- const legacyItems = await discoverLegacyDirectory(configFileDir, dirName);
406
- config.collections.push(...legacyItems);
407
- }
408
-
409
- // Ensure array exists even if empty
410
- config.collections = config.collections || [];
411
-
412
- // Log the final result
413
- const allCollections = config.collections || [];
414
- const fromCollectionsDir = allCollections.filter((c: any) => !c._isFromTablesDir).length;
415
- const fromTablesDir = allCollections.filter((c: any) => c._isFromTablesDir).length;
416
- const totalLoaded = allCollections.length;
417
-
418
- if (totalLoaded > 0) {
419
- if (fromTablesDir > 0) {
420
- MessageFormatter.success(`Successfully loaded ${totalLoaded} items total: ${fromCollectionsDir} from collections/ and ${fromTablesDir} from tables/`, { prefix: "Config" });
421
- } else {
422
- MessageFormatter.success(`Successfully loaded ${totalLoaded} collections from collections/`, { prefix: "Config" });
423
- }
424
- }
425
-
426
- // Log successful config loading
427
- if (actualConfigPath) {
428
- MessageFormatter.success(`Loaded config from: ${actualConfigPath}`, { prefix: "Config" });
429
- }
430
-
431
- // Validate configuration if requested
432
- if (validate) {
433
- let validation = validateCollectionsTablesConfig(config);
434
-
435
- // In strict mode, treat warnings as errors
436
- if (strictMode && validation.warnings.length > 0) {
437
- validation = {
438
- ...validation,
439
- isValid: false,
440
- errors: [...validation.errors, ...validation.warnings.map(w => ({ ...w, severity: "error" as const }))],
441
- warnings: []
442
- };
443
- }
444
-
445
- // Report validation results if requested
446
- if (reportValidation) {
447
- reportValidationResults(validation, { verbose: true });
448
- }
449
-
450
- // Throw error if validation fails in strict mode
451
- if (strictMode && !validation.isValid) {
452
- throw new Error(`Configuration validation failed in strict mode. Found ${validation.errors.length} validation errors.`);
453
- }
454
- }
455
-
456
- return config;
457
- };