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.
Files changed (233) hide show
  1. package/CHANGELOG.md +199 -0
  2. package/README.md +251 -29
  3. package/dist/adapters/AdapterFactory.d.ts +10 -3
  4. package/dist/adapters/AdapterFactory.js +213 -17
  5. package/dist/adapters/TablesDBAdapter.js +60 -17
  6. package/dist/backups/operations/bucketBackup.d.ts +19 -0
  7. package/dist/backups/operations/bucketBackup.js +197 -0
  8. package/dist/backups/operations/collectionBackup.d.ts +30 -0
  9. package/dist/backups/operations/collectionBackup.js +201 -0
  10. package/dist/backups/operations/comprehensiveBackup.d.ts +25 -0
  11. package/dist/backups/operations/comprehensiveBackup.js +238 -0
  12. package/dist/backups/schemas/bucketManifest.d.ts +93 -0
  13. package/dist/backups/schemas/bucketManifest.js +33 -0
  14. package/dist/backups/schemas/comprehensiveManifest.d.ts +108 -0
  15. package/dist/backups/schemas/comprehensiveManifest.js +32 -0
  16. package/dist/backups/tracking/centralizedTracking.d.ts +34 -0
  17. package/dist/backups/tracking/centralizedTracking.js +274 -0
  18. package/dist/cli/commands/configCommands.d.ts +8 -0
  19. package/dist/cli/commands/configCommands.js +160 -0
  20. package/dist/cli/commands/databaseCommands.d.ts +13 -0
  21. package/dist/cli/commands/databaseCommands.js +479 -0
  22. package/dist/cli/commands/functionCommands.d.ts +7 -0
  23. package/dist/cli/commands/functionCommands.js +289 -0
  24. package/dist/cli/commands/schemaCommands.d.ts +7 -0
  25. package/dist/cli/commands/schemaCommands.js +134 -0
  26. package/dist/cli/commands/transferCommands.d.ts +5 -0
  27. package/dist/cli/commands/transferCommands.js +384 -0
  28. package/dist/collections/attributes.d.ts +5 -4
  29. package/dist/collections/attributes.js +539 -246
  30. package/dist/collections/indexes.js +39 -37
  31. package/dist/collections/methods.d.ts +2 -16
  32. package/dist/collections/methods.js +90 -538
  33. package/dist/collections/transferOperations.d.ts +7 -0
  34. package/dist/collections/transferOperations.js +331 -0
  35. package/dist/collections/wipeOperations.d.ts +16 -0
  36. package/dist/collections/wipeOperations.js +328 -0
  37. package/dist/config/configMigration.d.ts +87 -0
  38. package/dist/config/configMigration.js +390 -0
  39. package/dist/config/configValidation.d.ts +66 -0
  40. package/dist/config/configValidation.js +358 -0
  41. package/dist/config/yamlConfig.d.ts +455 -1
  42. package/dist/config/yamlConfig.js +145 -52
  43. package/dist/databases/methods.js +3 -2
  44. package/dist/databases/setup.d.ts +1 -2
  45. package/dist/databases/setup.js +9 -87
  46. package/dist/examples/yamlTerminologyExample.d.ts +42 -0
  47. package/dist/examples/yamlTerminologyExample.js +269 -0
  48. package/dist/functions/deployments.js +11 -10
  49. package/dist/functions/methods.d.ts +1 -1
  50. package/dist/functions/methods.js +5 -4
  51. package/dist/init.js +9 -9
  52. package/dist/interactiveCLI.d.ts +8 -17
  53. package/dist/interactiveCLI.js +209 -1172
  54. package/dist/main.js +364 -21
  55. package/dist/migrations/afterImportActions.js +22 -30
  56. package/dist/migrations/appwriteToX.js +71 -25
  57. package/dist/migrations/dataLoader.js +35 -26
  58. package/dist/migrations/importController.js +29 -30
  59. package/dist/migrations/relationships.js +13 -12
  60. package/dist/migrations/services/ImportOrchestrator.js +16 -19
  61. package/dist/migrations/transfer.js +46 -46
  62. package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +3 -1
  63. package/dist/migrations/yaml/YamlImportConfigLoader.js +6 -3
  64. package/dist/migrations/yaml/YamlImportIntegration.d.ts +9 -3
  65. package/dist/migrations/yaml/YamlImportIntegration.js +22 -11
  66. package/dist/migrations/yaml/generateImportSchemas.d.ts +14 -1
  67. package/dist/migrations/yaml/generateImportSchemas.js +736 -7
  68. package/dist/schemas/authUser.d.ts +1 -1
  69. package/dist/setupController.js +3 -2
  70. package/dist/shared/backupMetadataSchema.d.ts +94 -0
  71. package/dist/shared/backupMetadataSchema.js +38 -0
  72. package/dist/shared/backupTracking.d.ts +18 -0
  73. package/dist/shared/backupTracking.js +176 -0
  74. package/dist/shared/confirmationDialogs.js +15 -15
  75. package/dist/shared/errorUtils.d.ts +54 -0
  76. package/dist/shared/errorUtils.js +95 -0
  77. package/dist/shared/functionManager.js +20 -19
  78. package/dist/shared/indexManager.js +12 -11
  79. package/dist/shared/jsonSchemaGenerator.js +10 -26
  80. package/dist/shared/logging.d.ts +51 -0
  81. package/dist/shared/logging.js +70 -0
  82. package/dist/shared/messageFormatter.d.ts +2 -0
  83. package/dist/shared/messageFormatter.js +10 -0
  84. package/dist/shared/migrationHelpers.d.ts +6 -16
  85. package/dist/shared/migrationHelpers.js +24 -21
  86. package/dist/shared/operationLogger.d.ts +8 -1
  87. package/dist/shared/operationLogger.js +11 -24
  88. package/dist/shared/operationQueue.d.ts +28 -1
  89. package/dist/shared/operationQueue.js +268 -66
  90. package/dist/shared/operationsTable.d.ts +26 -0
  91. package/dist/shared/operationsTable.js +286 -0
  92. package/dist/shared/operationsTableSchema.d.ts +48 -0
  93. package/dist/shared/operationsTableSchema.js +35 -0
  94. package/dist/shared/relationshipExtractor.d.ts +56 -0
  95. package/dist/shared/relationshipExtractor.js +138 -0
  96. package/dist/shared/schemaGenerator.d.ts +19 -1
  97. package/dist/shared/schemaGenerator.js +56 -75
  98. package/dist/storage/backupCompression.d.ts +20 -0
  99. package/dist/storage/backupCompression.js +67 -0
  100. package/dist/storage/methods.d.ts +16 -2
  101. package/dist/storage/methods.js +98 -14
  102. package/dist/users/methods.js +9 -8
  103. package/dist/utils/configDiscovery.d.ts +78 -0
  104. package/dist/utils/configDiscovery.js +430 -0
  105. package/dist/utils/directoryUtils.d.ts +22 -0
  106. package/dist/utils/directoryUtils.js +59 -0
  107. package/dist/utils/getClientFromConfig.d.ts +17 -8
  108. package/dist/utils/getClientFromConfig.js +162 -17
  109. package/dist/utils/helperFunctions.d.ts +16 -2
  110. package/dist/utils/helperFunctions.js +19 -5
  111. package/dist/utils/loadConfigs.d.ts +34 -9
  112. package/dist/utils/loadConfigs.js +236 -316
  113. package/dist/utils/pathResolvers.d.ts +53 -0
  114. package/dist/utils/pathResolvers.js +72 -0
  115. package/dist/utils/projectConfig.d.ts +119 -0
  116. package/dist/utils/projectConfig.js +171 -0
  117. package/dist/utils/retryFailedPromises.js +4 -2
  118. package/dist/utils/sessionAuth.d.ts +48 -0
  119. package/dist/utils/sessionAuth.js +164 -0
  120. package/dist/utils/sessionPreservationExample.d.ts +1666 -0
  121. package/dist/utils/sessionPreservationExample.js +101 -0
  122. package/dist/utils/setupFiles.js +301 -41
  123. package/dist/utils/typeGuards.d.ts +35 -0
  124. package/dist/utils/typeGuards.js +57 -0
  125. package/dist/utils/versionDetection.js +145 -9
  126. package/dist/utils/yamlConverter.d.ts +53 -3
  127. package/dist/utils/yamlConverter.js +232 -13
  128. package/dist/utils/yamlLoader.d.ts +70 -0
  129. package/dist/utils/yamlLoader.js +263 -0
  130. package/dist/utilsController.d.ts +36 -3
  131. package/dist/utilsController.js +186 -56
  132. package/package.json +12 -2
  133. package/src/adapters/AdapterFactory.ts +263 -35
  134. package/src/adapters/TablesDBAdapter.ts +225 -36
  135. package/src/backups/operations/bucketBackup.ts +277 -0
  136. package/src/backups/operations/collectionBackup.ts +310 -0
  137. package/src/backups/operations/comprehensiveBackup.ts +342 -0
  138. package/src/backups/schemas/bucketManifest.ts +78 -0
  139. package/src/backups/schemas/comprehensiveManifest.ts +76 -0
  140. package/src/backups/tracking/centralizedTracking.ts +352 -0
  141. package/src/cli/commands/configCommands.ts +194 -0
  142. package/src/cli/commands/databaseCommands.ts +635 -0
  143. package/src/cli/commands/functionCommands.ts +379 -0
  144. package/src/cli/commands/schemaCommands.ts +163 -0
  145. package/src/cli/commands/transferCommands.ts +457 -0
  146. package/src/collections/attributes.ts +900 -621
  147. package/src/collections/attributes.ts.backup +1555 -0
  148. package/src/collections/indexes.ts +116 -114
  149. package/src/collections/methods.ts +295 -968
  150. package/src/collections/transferOperations.ts +516 -0
  151. package/src/collections/wipeOperations.ts +501 -0
  152. package/src/config/README.md +274 -0
  153. package/src/config/configMigration.ts +575 -0
  154. package/src/config/configValidation.ts +445 -0
  155. package/src/config/yamlConfig.ts +168 -55
  156. package/src/databases/methods.ts +3 -2
  157. package/src/databases/setup.ts +11 -138
  158. package/src/examples/yamlTerminologyExample.ts +341 -0
  159. package/src/functions/deployments.ts +14 -12
  160. package/src/functions/methods.ts +11 -11
  161. package/src/functions/templates/hono-typescript/README.md +286 -0
  162. package/src/functions/templates/hono-typescript/package.json +26 -0
  163. package/src/functions/templates/hono-typescript/src/adapters/request.ts +74 -0
  164. package/src/functions/templates/hono-typescript/src/adapters/response.ts +106 -0
  165. package/src/functions/templates/hono-typescript/src/app.ts +180 -0
  166. package/src/functions/templates/hono-typescript/src/context.ts +103 -0
  167. package/src/functions/templates/hono-typescript/src/index.ts +54 -0
  168. package/src/functions/templates/hono-typescript/src/middleware/appwrite.ts +119 -0
  169. package/src/functions/templates/hono-typescript/tsconfig.json +20 -0
  170. package/src/functions/templates/typescript-node/package.json +2 -1
  171. package/src/functions/templates/typescript-node/src/context.ts +103 -0
  172. package/src/functions/templates/typescript-node/src/index.ts +18 -12
  173. package/src/functions/templates/uv/pyproject.toml +1 -0
  174. package/src/functions/templates/uv/src/context.py +125 -0
  175. package/src/functions/templates/uv/src/index.py +35 -5
  176. package/src/init.ts +9 -11
  177. package/src/interactiveCLI.ts +274 -1563
  178. package/src/main.ts +418 -24
  179. package/src/migrations/afterImportActions.ts +71 -44
  180. package/src/migrations/appwriteToX.ts +100 -34
  181. package/src/migrations/dataLoader.ts +48 -34
  182. package/src/migrations/importController.ts +44 -39
  183. package/src/migrations/relationships.ts +28 -18
  184. package/src/migrations/services/ImportOrchestrator.ts +24 -27
  185. package/src/migrations/transfer.ts +159 -121
  186. package/src/migrations/yaml/YamlImportConfigLoader.ts +11 -4
  187. package/src/migrations/yaml/YamlImportIntegration.ts +47 -20
  188. package/src/migrations/yaml/generateImportSchemas.ts +751 -12
  189. package/src/setupController.ts +3 -2
  190. package/src/shared/backupMetadataSchema.ts +93 -0
  191. package/src/shared/backupTracking.ts +211 -0
  192. package/src/shared/confirmationDialogs.ts +19 -19
  193. package/src/shared/errorUtils.ts +110 -0
  194. package/src/shared/functionManager.ts +21 -20
  195. package/src/shared/indexManager.ts +12 -11
  196. package/src/shared/jsonSchemaGenerator.ts +38 -52
  197. package/src/shared/logging.ts +75 -0
  198. package/src/shared/messageFormatter.ts +14 -1
  199. package/src/shared/migrationHelpers.ts +45 -38
  200. package/src/shared/operationLogger.ts +11 -36
  201. package/src/shared/operationQueue.ts +322 -93
  202. package/src/shared/operationsTable.ts +338 -0
  203. package/src/shared/operationsTableSchema.ts +60 -0
  204. package/src/shared/relationshipExtractor.ts +214 -0
  205. package/src/shared/schemaGenerator.ts +179 -219
  206. package/src/storage/backupCompression.ts +88 -0
  207. package/src/storage/methods.ts +131 -34
  208. package/src/users/methods.ts +11 -9
  209. package/src/utils/configDiscovery.ts +502 -0
  210. package/src/utils/directoryUtils.ts +61 -0
  211. package/src/utils/getClientFromConfig.ts +205 -22
  212. package/src/utils/helperFunctions.ts +23 -5
  213. package/src/utils/loadConfigs.ts +313 -345
  214. package/src/utils/pathResolvers.ts +81 -0
  215. package/src/utils/projectConfig.ts +299 -0
  216. package/src/utils/retryFailedPromises.ts +4 -2
  217. package/src/utils/sessionAuth.ts +230 -0
  218. package/src/utils/setupFiles.ts +322 -54
  219. package/src/utils/typeGuards.ts +65 -0
  220. package/src/utils/versionDetection.ts +218 -64
  221. package/src/utils/yamlConverter.ts +296 -13
  222. package/src/utils/yamlLoader.ts +364 -0
  223. package/src/utilsController.ts +314 -110
  224. package/tests/README.md +497 -0
  225. package/tests/adapters/AdapterFactory.test.ts +277 -0
  226. package/tests/integration/syncOperations.test.ts +463 -0
  227. package/tests/jest.config.js +25 -0
  228. package/tests/migration/configMigration.test.ts +546 -0
  229. package/tests/setup.ts +62 -0
  230. package/tests/testUtils.ts +340 -0
  231. package/tests/utils/loadConfigs.test.ts +350 -0
  232. package/tests/validation/configValidation.test.ts +412 -0
  233. package/src/utils/schemaStrings.ts +0 -517
@@ -1,23 +1,26 @@
1
1
  /**
2
2
  * Version Detection Utility for Appwrite API Compatibility
3
- *
3
+ *
4
4
  * This module provides functions to detect whether an Appwrite instance
5
5
  * supports the new TablesDB API or uses the legacy Databases API.
6
- *
6
+ *
7
7
  * Detection Strategy:
8
8
  * 1. Primary: Test TablesDB-specific endpoint availability
9
- * 2. Secondary: Health endpoint version check
9
+ * 2. Secondary: Health endpoint version check
10
10
  * 3. Fallback: Default to legacy mode for safety
11
11
  */
12
12
 
13
+ import { logger } from '../shared/logging.js';
14
+ import { MessageFormatter } from '../shared/messageFormatter.js';
15
+
13
16
  export type ApiMode = 'legacy' | 'tablesdb';
14
17
 
15
- export interface VersionDetectionResult {
16
- apiMode: ApiMode;
17
- detectionMethod: 'endpoint_probe' | 'health_check' | 'fallback';
18
- serverVersion?: string;
19
- confidence: 'high' | 'medium' | 'low';
20
- }
18
+ export interface VersionDetectionResult {
19
+ apiMode: ApiMode;
20
+ detectionMethod: 'endpoint_probe' | 'health_check' | 'fallback';
21
+ serverVersion?: string;
22
+ confidence: 'high' | 'medium' | 'low';
23
+ }
21
24
 
22
25
  /**
23
26
  * Detects Appwrite API version and TablesDB support
@@ -32,36 +35,115 @@ export async function detectAppwriteVersion(
32
35
  project: string,
33
36
  apiKey: string
34
37
  ): Promise<VersionDetectionResult> {
38
+ const startTime = Date.now();
35
39
  // Clean endpoint URL
36
40
  const cleanEndpoint = endpoint.replace(/\/$/, '');
37
-
41
+
42
+ logger.info('Starting Appwrite version detection', {
43
+ endpoint: cleanEndpoint,
44
+ project,
45
+ operation: 'detectAppwriteVersion'
46
+ });
47
+
48
+ // STEP 1: Check server version FIRST
49
+ const serverVersion = await fetchServerVersion(cleanEndpoint);
50
+
51
+ if (serverVersion && !isVersionAtLeast(serverVersion, '1.8.0')) {
52
+ // Server < 1.8.0 doesn't support TablesDB
53
+ logger.info('Server version below 1.8.0 - using legacy adapter', {
54
+ serverVersion,
55
+ operation: 'detectAppwriteVersion'
56
+ });
57
+ return {
58
+ apiMode: 'legacy',
59
+ detectionMethod: 'health_check',
60
+ serverVersion,
61
+ confidence: 'high'
62
+ };
63
+ }
64
+
65
+ // STEP 2: Only proceed with endpoint probe if version >= 1.8.0 or version unknown
38
66
  // Try primary detection method: TablesDB endpoint probe
39
67
  try {
68
+ logger.debug('Attempting TablesDB endpoint probe', {
69
+ endpoint: cleanEndpoint,
70
+ serverVersion: serverVersion || 'unknown',
71
+ operation: 'detectAppwriteVersion'
72
+ });
73
+
74
+ const probeStartTime = Date.now();
40
75
  const tablesDbResult = await probeTablesDbEndpoint(cleanEndpoint, project, apiKey);
76
+ const probeDuration = Date.now() - probeStartTime;
77
+
41
78
  if (tablesDbResult.apiMode === 'tablesdb') {
79
+ logger.info('TablesDB detected via endpoint probe', {
80
+ endpoint: cleanEndpoint,
81
+ detectionMethod: tablesDbResult.detectionMethod,
82
+ confidence: tablesDbResult.confidence,
83
+ probeDuration,
84
+ totalDuration: Date.now() - startTime,
85
+ operation: 'detectAppwriteVersion'
86
+ });
42
87
  return tablesDbResult;
43
88
  }
44
89
  } catch (error) {
45
- console.warn('TablesDB endpoint probe failed:', error instanceof Error ? error.message : 'Unknown error');
90
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
91
+ MessageFormatter.warning(`TablesDB endpoint probe failed: ${errorMessage}`, { prefix: "Version Detection" });
92
+ logger.warn('TablesDB endpoint probe failed', {
93
+ endpoint: cleanEndpoint,
94
+ error: errorMessage,
95
+ operation: 'detectAppwriteVersion'
96
+ });
46
97
  }
47
98
 
48
99
  // Try secondary detection method: SDK feature detection
49
100
  try {
101
+ logger.debug('Attempting SDK capability probe', {
102
+ endpoint: cleanEndpoint,
103
+ operation: 'detectAppwriteVersion'
104
+ });
105
+
106
+ const sdkProbeStartTime = Date.now();
50
107
  const sdkResult = await probeSdkCapabilities();
108
+ const sdkProbeDuration = Date.now() - sdkProbeStartTime;
109
+
51
110
  if (sdkResult.apiMode === 'tablesdb') {
111
+ logger.info('TablesDB detected via SDK capability probe', {
112
+ endpoint: cleanEndpoint,
113
+ detectionMethod: sdkResult.detectionMethod,
114
+ confidence: sdkResult.confidence,
115
+ sdkProbeDuration,
116
+ totalDuration: Date.now() - startTime,
117
+ operation: 'detectAppwriteVersion'
118
+ });
52
119
  return sdkResult;
53
120
  }
54
121
  } catch (error) {
55
- console.warn('SDK capability probe failed:', error instanceof Error ? error.message : 'Unknown error');
122
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
123
+ MessageFormatter.warning(`SDK capability probe failed: ${errorMessage}`, { prefix: "Version Detection" });
124
+ logger.warn('SDK capability probe failed', {
125
+ endpoint: cleanEndpoint,
126
+ error: errorMessage,
127
+ operation: 'detectAppwriteVersion'
128
+ });
56
129
  }
57
-
58
- // Fallback to legacy mode
59
- return {
60
- apiMode: 'legacy',
61
- detectionMethod: 'fallback',
62
- confidence: 'low'
63
- };
64
- }
130
+
131
+ // Fallback to legacy mode
132
+ const fallbackResult = {
133
+ apiMode: 'legacy' as ApiMode,
134
+ detectionMethod: 'fallback' as const,
135
+ confidence: 'low' as const
136
+ };
137
+
138
+ logger.info('Falling back to legacy mode', {
139
+ endpoint: cleanEndpoint,
140
+ totalDuration: Date.now() - startTime,
141
+ result: fallbackResult,
142
+ operation: 'detectAppwriteVersion'
143
+ });
144
+
145
+ return fallbackResult;
146
+ }
65
147
 
66
148
  /**
67
149
  * Test TablesDB endpoint availability - most reliable detection method
@@ -71,7 +153,16 @@ async function probeTablesDbEndpoint(
71
153
  project: string,
72
154
  apiKey: string
73
155
  ): Promise<VersionDetectionResult> {
74
- const response = await fetch(`${endpoint}/tablesdb/`, {
156
+ const startTime = Date.now();
157
+ const url = `${endpoint}/tablesdb/`;
158
+
159
+ logger.debug('Probing TablesDB endpoint', {
160
+ url,
161
+ project,
162
+ operation: 'probeTablesDbEndpoint'
163
+ });
164
+
165
+ const response = await fetch(url, {
75
166
  method: 'GET',
76
167
  headers: {
77
168
  'Content-Type': 'application/json',
@@ -81,19 +172,47 @@ async function probeTablesDbEndpoint(
81
172
  // Short timeout for faster detection
82
173
  signal: AbortSignal.timeout(5000)
83
174
  });
84
-
85
- if (response.ok || response.status === 404) {
86
- // 200 = TablesDB available, 404 = endpoint exists but no tables
87
- // Both indicate TablesDB support
88
- return {
89
- apiMode: 'tablesdb',
90
- detectionMethod: 'endpoint_probe',
91
- confidence: 'high'
92
- };
93
- }
94
-
175
+
176
+ const duration = Date.now() - startTime;
177
+
178
+ logger.debug('TablesDB endpoint response received', {
179
+ url,
180
+ status: response.status,
181
+ statusText: response.statusText,
182
+ duration,
183
+ operation: 'probeTablesDbEndpoint'
184
+ });
185
+
186
+ if (response.ok) {
187
+ // ONLY 200 OK means TablesDB available
188
+ // 404 means endpoint doesn't exist (server < 1.8.0)
189
+ const result = {
190
+ apiMode: 'tablesdb' as ApiMode,
191
+ detectionMethod: 'endpoint_probe' as const,
192
+ confidence: 'high' as const
193
+ };
194
+
195
+ logger.info('TablesDB endpoint probe successful', {
196
+ url,
197
+ status: response.status,
198
+ result,
199
+ duration,
200
+ operation: 'probeTablesDbEndpoint'
201
+ });
202
+
203
+ return result;
204
+ }
205
+
95
206
  // 501 Not Implemented or other errors = no TablesDB support
96
- throw new Error(`TablesDB endpoint returned ${response.status}: ${response.statusText}`);
207
+ const error = new Error(`TablesDB endpoint returned ${response.status}: ${response.statusText}`);
208
+ logger.debug('TablesDB endpoint probe failed', {
209
+ url,
210
+ status: response.status,
211
+ statusText: response.statusText,
212
+ duration,
213
+ operation: 'probeTablesDbEndpoint'
214
+ });
215
+ throw error;
97
216
  }
98
217
 
99
218
  /**
@@ -196,20 +315,55 @@ export async function detectAppwriteVersionCached(
196
315
  apiKey: string,
197
316
  forceRefresh: boolean = false
198
317
  ): Promise<VersionDetectionResult> {
318
+ const startTime = Date.now();
319
+
320
+ logger.debug('Version detection with cache requested', {
321
+ endpoint,
322
+ project,
323
+ forceRefresh,
324
+ operation: 'detectAppwriteVersionCached'
325
+ });
326
+
199
327
  // Check cache first (unless force refresh)
200
328
  if (!forceRefresh) {
201
329
  const cached = detectionCache.get(endpoint, project);
202
330
  if (cached) {
331
+ logger.info('Using cached version detection result', {
332
+ endpoint,
333
+ project,
334
+ cachedResult: cached,
335
+ operation: 'detectAppwriteVersionCached'
336
+ });
203
337
  return cached;
204
338
  }
339
+ logger.debug('No cached result found, performing fresh detection', {
340
+ endpoint,
341
+ project,
342
+ operation: 'detectAppwriteVersionCached'
343
+ });
344
+ } else {
345
+ logger.debug('Force refresh requested, bypassing cache', {
346
+ endpoint,
347
+ project,
348
+ operation: 'detectAppwriteVersionCached'
349
+ });
205
350
  }
206
-
351
+
207
352
  // Perform fresh detection
208
353
  const result = await detectAppwriteVersion(endpoint, project, apiKey);
209
-
354
+ const totalDuration = Date.now() - startTime;
355
+
210
356
  // Cache the result
211
357
  detectionCache.set(endpoint, project, result);
212
-
358
+
359
+ logger.info('Version detection completed and cached', {
360
+ endpoint,
361
+ project,
362
+ result,
363
+ totalDuration,
364
+ operation: 'detectAppwriteVersionCached'
365
+ });
366
+
213
367
  return result;
214
368
  }
215
369
 
@@ -262,31 +416,31 @@ export async function detectSdkSupport(): Promise<{
262
416
  */
263
417
  export function clearVersionDetectionCache(): void {
264
418
  detectionCache.clear();
265
- }
266
-
267
- /**
268
- * Fetch server version from /health/version (no auth required)
269
- */
270
- export async function fetchServerVersion(endpoint: string): Promise<string | null> {
271
- try {
272
- const clean = endpoint.replace(/\/$/, '');
273
- const res = await fetch(`${clean}/health/version`, { method: 'GET', signal: AbortSignal.timeout(5000) });
274
- if (!res.ok) return null;
275
- const data = await res.json().catch(() => null) as any;
276
- const version = (data && (data.version || data.build || data.release)) ?? null;
277
- return typeof version === 'string' ? version : null;
278
- } catch {
279
- return null;
280
- }
281
- }
282
-
283
- /** Compare semantic versions (basic) */
284
- export function isVersionAtLeast(current: string | undefined, target: string): boolean {
285
- if (!current) return false;
286
- const toNums = (v: string) => v.split('.').map(n => parseInt(n, 10));
287
- const [a1=0,a2=0,a3=0] = toNums(current);
288
- const [b1,b2,b3] = toNums(target);
289
- if (a1 !== b1) return a1 > b1;
290
- if (a2 !== b2) return a2 > b2;
291
- return a3 >= b3;
292
- }
419
+ }
420
+
421
+ /**
422
+ * Fetch server version from /health/version (no auth required)
423
+ */
424
+ export async function fetchServerVersion(endpoint: string): Promise<string | null> {
425
+ try {
426
+ const clean = endpoint.replace(/\/$/, '');
427
+ const res = await fetch(`${clean}/health/version`, { method: 'GET', signal: AbortSignal.timeout(5000) });
428
+ if (!res.ok) return null;
429
+ const data = await res.json().catch(() => null) as any;
430
+ const version = (data && (data.version || data.build || data.release)) ?? null;
431
+ return typeof version === 'string' ? version : null;
432
+ } catch {
433
+ return null;
434
+ }
435
+ }
436
+
437
+ /** Compare semantic versions (basic) */
438
+ export function isVersionAtLeast(current: string | undefined, target: string): boolean {
439
+ if (!current) return false;
440
+ const toNums = (v: string) => v.split('.').map(n => parseInt(n, 10));
441
+ const [a1=0,a2=0,a3=0] = toNums(current);
442
+ const [b1,b2,b3] = toNums(target);
443
+ if (a1 !== b1) return a1 > b1;
444
+ if (a2 !== b2) return a2 > b2;
445
+ return a3 >= b3;
446
+ }