appwrite-utils-cli 1.5.2 → 1.6.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 (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 +478 -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 +181 -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 +278 -1596
  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
@@ -7,17 +7,24 @@
7
7
  */
8
8
 
9
9
  import type { AppwriteConfig } from "appwrite-utils";
10
- import { detectAppwriteVersionCached, type ApiMode, type VersionDetectionResult } from "../utils/versionDetection.js";
10
+ import { detectAppwriteVersionCached, isVersionAtLeast, type ApiMode, type VersionDetectionResult } from "../utils/versionDetection.js";
11
11
  import type { DatabaseAdapter } from './DatabaseAdapter.js';
12
12
  import { TablesDBAdapter } from './TablesDBAdapter.js';
13
13
  import { LegacyAdapter } from './LegacyAdapter.js';
14
+ import { logger } from '../shared/logging.js';
15
+ import { getClientWithAuth } from '../utils/getClientFromConfig.js';
16
+ import { isValidSessionCookie } from '../utils/sessionAuth.js';
17
+ import { MessageFormatter } from '../shared/messageFormatter.js';
14
18
 
15
19
  export interface AdapterFactoryConfig {
16
20
  appwriteEndpoint: string;
17
21
  appwriteProject: string;
18
- appwriteKey: string;
22
+ appwriteKey?: string; // Made optional to support session-only auth
19
23
  apiMode?: 'auto' | 'legacy' | 'tablesdb';
20
24
  forceRefresh?: boolean; // Skip detection cache
25
+ sessionCookie?: string; // Session authentication support
26
+ authMethod?: 'session' | 'apikey' | 'auto'; // Authentication method preference
27
+ preConfiguredClient?: any; // Pre-configured authenticated client
21
28
  }
22
29
 
23
30
  export interface AdapterFactoryResult {
@@ -38,12 +45,36 @@ export class AdapterFactory {
38
45
  * Create a database adapter based on configuration and detection
39
46
  */
40
47
  static async create(config: AdapterFactoryConfig): Promise<AdapterFactoryResult> {
48
+ const startTime = Date.now();
49
+
50
+ // Validate authentication configuration
51
+ this.validateAuthConfig(config);
52
+
41
53
  const cacheKey = `${config.appwriteEndpoint}:${config.appwriteProject}:${config.apiMode || 'auto'}`;
42
-
54
+
55
+ logger.info('Creating database adapter', {
56
+ endpoint: config.appwriteEndpoint,
57
+ project: config.appwriteProject,
58
+ requestedApiMode: config.apiMode || 'auto',
59
+ authMethod: config.authMethod || 'auto',
60
+ hasSessionCookie: !!config.sessionCookie,
61
+ hasPreConfiguredClient: !!config.preConfiguredClient,
62
+ forceRefresh: config.forceRefresh,
63
+ cacheKey,
64
+ operation: 'AdapterFactory.create'
65
+ });
66
+
43
67
  // Check cache first (unless force refresh)
44
68
  if (!config.forceRefresh) {
45
69
  const cached = this.getCachedAdapter(cacheKey);
46
70
  if (cached) {
71
+ const cacheAge = Date.now() - cached.timestamp;
72
+ logger.info('Using cached adapter', {
73
+ cacheKey,
74
+ cacheAge,
75
+ apiMode: cached.adapter.getApiMode(),
76
+ operation: 'AdapterFactory.create'
77
+ });
47
78
  return {
48
79
  adapter: cached.adapter,
49
80
  apiMode: cached.adapter.getApiMode(),
@@ -55,27 +86,84 @@ export class AdapterFactory {
55
86
  // Determine API mode
56
87
  let apiMode: ApiMode;
57
88
  let detectionResult: VersionDetectionResult | undefined;
58
-
89
+
59
90
  if (config.apiMode && config.apiMode !== 'auto') {
60
91
  // Use explicitly configured mode
61
92
  apiMode = config.apiMode;
93
+ logger.info('Using explicitly configured API mode', {
94
+ apiMode,
95
+ endpoint: config.appwriteEndpoint,
96
+ operation: 'AdapterFactory.create'
97
+ });
62
98
  } else {
63
99
  // Auto-detect API mode
100
+ logger.info('Starting API mode auto-detection', {
101
+ endpoint: config.appwriteEndpoint,
102
+ project: config.appwriteProject,
103
+ forceRefresh: config.forceRefresh,
104
+ operation: 'AdapterFactory.create'
105
+ });
106
+
107
+ const detectionStartTime = Date.now();
108
+ // For version detection, we need some form of authentication
109
+ const authKey = config.appwriteKey || '';
64
110
  detectionResult = await detectAppwriteVersionCached(
65
111
  config.appwriteEndpoint,
66
112
  config.appwriteProject,
67
- config.appwriteKey,
113
+ authKey,
68
114
  config.forceRefresh
69
115
  );
116
+ const detectionDuration = Date.now() - detectionStartTime;
117
+
70
118
  apiMode = detectionResult.apiMode;
119
+
120
+ logger.info('API mode detection completed', {
121
+ apiMode,
122
+ detectionMethod: detectionResult.detectionMethod,
123
+ confidence: detectionResult.confidence,
124
+ serverVersion: detectionResult.serverVersion,
125
+ detectionDuration,
126
+ endpoint: config.appwriteEndpoint,
127
+ operation: 'AdapterFactory.create'
128
+ });
129
+
130
+ // Add version-based safety check to prevent using TablesDB on old servers
131
+ if (detectionResult.serverVersion &&
132
+ !isVersionAtLeast(detectionResult.serverVersion, '1.8.0') &&
133
+ apiMode === 'tablesdb') {
134
+ logger.warn('Overriding TablesDB detection - server version too old', {
135
+ serverVersion: detectionResult.serverVersion,
136
+ detectedMode: apiMode,
137
+ overrideMode: 'legacy',
138
+ operation: 'AdapterFactory.create'
139
+ });
140
+ apiMode = 'legacy';
141
+ }
71
142
  }
72
143
 
73
144
  // Create appropriate adapter
145
+ logger.info('Creating adapter instance', {
146
+ apiMode,
147
+ endpoint: config.appwriteEndpoint,
148
+ operation: 'AdapterFactory.create'
149
+ });
150
+
151
+ const adapterStartTime = Date.now();
74
152
  const result = await this.createAdapter(config, apiMode);
75
-
153
+ const adapterDuration = Date.now() - adapterStartTime;
154
+
76
155
  // Cache the result
77
156
  this.setCachedAdapter(cacheKey, result.adapter);
78
-
157
+
158
+ const totalDuration = Date.now() - startTime;
159
+ logger.info('Adapter creation completed', {
160
+ apiMode,
161
+ adapterDuration,
162
+ totalDuration,
163
+ cached: true,
164
+ operation: 'AdapterFactory.create'
165
+ });
166
+
79
167
  return {
80
168
  ...result,
81
169
  apiMode,
@@ -116,24 +204,76 @@ export class AdapterFactory {
116
204
  private static async createTablesDBAdapter(
117
205
  config: AdapterFactoryConfig
118
206
  ): Promise<{ adapter: DatabaseAdapter; client: any }> {
207
+ const startTime = Date.now();
208
+
119
209
  try {
210
+ logger.info('Loading TablesDB SDK', {
211
+ endpoint: config.appwriteEndpoint,
212
+ operation: 'createTablesDBAdapter'
213
+ });
214
+
120
215
  // Dynamic import of TablesDB SDK
216
+ const importStartTime = Date.now();
121
217
  const { Client, TablesDB } = await import('node-appwrite-tablesdb');
122
-
123
- const client = new Client()
124
- .setEndpoint(config.appwriteEndpoint)
125
- .setProject(config.appwriteProject)
126
- .setKey(config.appwriteKey);
127
-
218
+ const importDuration = Date.now() - importStartTime;
219
+
220
+ logger.debug('TablesDB SDK import successful', {
221
+ importDuration,
222
+ operation: 'createTablesDBAdapter'
223
+ });
224
+
225
+ // Use pre-configured client or create session-aware client with TablesDB Client
226
+ let client: any;
227
+ if (config.preConfiguredClient) {
228
+ client = config.preConfiguredClient;
229
+ } else {
230
+ client = new Client()
231
+ .setEndpoint(config.appwriteEndpoint)
232
+ .setProject(config.appwriteProject);
233
+
234
+ // Set authentication method based on priority
235
+ if (config.sessionCookie && isValidSessionCookie(config.sessionCookie)) {
236
+ (client as any).setSession(config.sessionCookie);
237
+ logger.debug('Using session authentication for TablesDB adapter', {
238
+ project: config.appwriteProject,
239
+ operation: 'createTablesDBAdapter'
240
+ });
241
+ } else if (config.appwriteKey) {
242
+ client.setKey(config.appwriteKey);
243
+ logger.debug('Using API key authentication for TablesDB adapter', {
244
+ project: config.appwriteProject,
245
+ operation: 'createTablesDBAdapter'
246
+ });
247
+ }
248
+ }
249
+
128
250
  const tablesDB = new TablesDB(client);
129
251
  const adapter = new TablesDBAdapter(tablesDB);
130
-
252
+
253
+ const totalDuration = Date.now() - startTime;
254
+ logger.info('TablesDB adapter created successfully', {
255
+ totalDuration,
256
+ importDuration,
257
+ endpoint: config.appwriteEndpoint,
258
+ operation: 'createTablesDBAdapter'
259
+ });
260
+
131
261
  return { adapter, client };
132
-
262
+
133
263
  } catch (error) {
134
- console.warn('Failed to load TablesDB SDK, falling back to legacy:', error);
135
-
136
- // Fallback to legacy adapter if TablesDB SDK is not available
264
+ const errorDuration = Date.now() - startTime;
265
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
266
+
267
+ MessageFormatter.warning('Failed to create TablesDB adapter - falling back to legacy', { prefix: "Adapter" });
268
+
269
+ logger.warn('TablesDB adapter creation failed, falling back to legacy', {
270
+ error: errorMessage,
271
+ errorDuration,
272
+ endpoint: config.appwriteEndpoint,
273
+ operation: 'createTablesDBAdapter'
274
+ });
275
+
276
+ // Fallback to legacy adapter if TablesDB creation fails
137
277
  return this.createLegacyAdapter(config);
138
278
  }
139
279
  }
@@ -144,22 +284,74 @@ export class AdapterFactory {
144
284
  private static async createLegacyAdapter(
145
285
  config: AdapterFactoryConfig
146
286
  ): Promise<{ adapter: DatabaseAdapter; client: any }> {
287
+ const startTime = Date.now();
288
+
147
289
  try {
290
+ logger.info('Loading legacy Appwrite SDK', {
291
+ endpoint: config.appwriteEndpoint,
292
+ operation: 'createLegacyAdapter'
293
+ });
294
+
148
295
  // Dynamic import of legacy SDK
296
+ const importStartTime = Date.now();
149
297
  const { Client, Databases } = await import('node-appwrite');
150
-
151
- const client = new Client()
152
- .setEndpoint(config.appwriteEndpoint)
153
- .setProject(config.appwriteProject)
154
- .setKey(config.appwriteKey);
155
-
298
+ const importDuration = Date.now() - importStartTime;
299
+
300
+ logger.debug('Legacy SDK import successful', {
301
+ importDuration,
302
+ operation: 'createLegacyAdapter'
303
+ });
304
+
305
+ // Use pre-configured client or create session-aware client with Legacy Client
306
+ let client: any;
307
+ if (config.preConfiguredClient) {
308
+ client = config.preConfiguredClient;
309
+ } else {
310
+ client = new Client()
311
+ .setEndpoint(config.appwriteEndpoint)
312
+ .setProject(config.appwriteProject);
313
+
314
+ // Set authentication method based on priority
315
+ if (config.sessionCookie && isValidSessionCookie(config.sessionCookie)) {
316
+ (client as any).setSession(config.sessionCookie);
317
+ logger.debug('Using session authentication for Legacy adapter', {
318
+ project: config.appwriteProject,
319
+ operation: 'createLegacyAdapter'
320
+ });
321
+ } else if (config.appwriteKey) {
322
+ client.setKey(config.appwriteKey);
323
+ logger.debug('Using API key authentication for Legacy adapter', {
324
+ project: config.appwriteProject,
325
+ operation: 'createLegacyAdapter'
326
+ });
327
+ }
328
+ }
329
+
156
330
  const databases = new Databases(client);
157
331
  const adapter = new LegacyAdapter(databases);
158
-
332
+
333
+ const totalDuration = Date.now() - startTime;
334
+ logger.info('Legacy adapter created successfully', {
335
+ totalDuration,
336
+ importDuration,
337
+ endpoint: config.appwriteEndpoint,
338
+ operation: 'createLegacyAdapter'
339
+ });
340
+
159
341
  return { adapter, client };
160
-
342
+
161
343
  } catch (error) {
162
- throw new Error(`Failed to load legacy Appwrite SDK: ${error instanceof Error ? error.message : 'Unknown error'}`);
344
+ const errorDuration = Date.now() - startTime;
345
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
346
+
347
+ logger.error('Failed to load legacy Appwrite SDK', {
348
+ error: errorMessage,
349
+ errorDuration,
350
+ endpoint: config.appwriteEndpoint,
351
+ operation: 'createLegacyAdapter'
352
+ });
353
+
354
+ throw new Error(`Failed to load legacy Appwrite SDK: ${errorMessage}`);
163
355
  }
164
356
  }
165
357
 
@@ -198,6 +390,39 @@ export class AdapterFactory {
198
390
  static clearCache(): void {
199
391
  this.cache.clear();
200
392
  }
393
+
394
+ /**
395
+ * Validate authentication configuration
396
+ */
397
+ private static validateAuthConfig(config: AdapterFactoryConfig): void {
398
+ const hasApiKey = config.appwriteKey && config.appwriteKey.trim().length > 0;
399
+ const hasSessionCookie = config.sessionCookie && isValidSessionCookie(config.sessionCookie);
400
+ const hasPreConfiguredClient = !!config.preConfiguredClient;
401
+
402
+ // Must have at least one authentication method
403
+ if (!hasApiKey && !hasSessionCookie && !hasPreConfiguredClient) {
404
+ throw new Error(
405
+ `No valid authentication method provided for project ${config.appwriteProject}. ` +
406
+ `Please provide an API key, session cookie, or pre-configured client.`
407
+ );
408
+ }
409
+
410
+ // Validate session cookie format if provided
411
+ if (config.sessionCookie && !isValidSessionCookie(config.sessionCookie)) {
412
+ throw new Error(
413
+ `Invalid session cookie format provided for project ${config.appwriteProject}. ` +
414
+ `Session cookie must be a valid JWT token.`
415
+ );
416
+ }
417
+
418
+ logger.debug('Authentication configuration validated', {
419
+ hasApiKey,
420
+ hasSessionCookie,
421
+ hasPreConfiguredClient,
422
+ authMethod: config.authMethod || 'auto',
423
+ operation: 'validateAuthConfig'
424
+ });
425
+ }
201
426
 
202
427
  /**
203
428
  * Test connection and API capabilities
@@ -254,16 +479,18 @@ export class AdapterFactory {
254
479
  export async function createDatabaseAdapter(
255
480
  endpoint: string,
256
481
  project: string,
257
- apiKey: string,
258
- mode: 'auto' | 'legacy' | 'tablesdb' = 'auto'
482
+ apiKey?: string,
483
+ mode: 'auto' | 'legacy' | 'tablesdb' = 'auto',
484
+ sessionCookie?: string
259
485
  ): Promise<DatabaseAdapter> {
260
486
  const result = await AdapterFactory.create({
261
487
  appwriteEndpoint: endpoint,
262
488
  appwriteProject: project,
263
489
  appwriteKey: apiKey,
264
- apiMode: mode
490
+ apiMode: mode,
491
+ sessionCookie
265
492
  });
266
-
493
+
267
494
  return result.adapter;
268
495
  }
269
496
 
@@ -273,21 +500,22 @@ export async function createDatabaseAdapter(
273
500
  export async function getApiCapabilities(
274
501
  endpoint: string,
275
502
  project: string,
276
- apiKey: string
503
+ apiKey?: string,
504
+ sessionCookie?: string
277
505
  ): Promise<{
278
506
  apiMode: ApiMode;
279
507
  terminology: { container: string; item: string; service: string };
280
508
  capabilities: string[];
281
509
  }> {
282
- const adapter = await createDatabaseAdapter(endpoint, project, apiKey, 'auto');
510
+ const adapter = await createDatabaseAdapter(endpoint, project, apiKey, 'auto', sessionCookie);
283
511
  const metadata = adapter.getMetadata();
284
-
512
+
285
513
  const capabilities = [];
286
514
  if (metadata.capabilities.bulkOperations) capabilities.push('Bulk Operations');
287
515
  if (metadata.capabilities.advancedQueries) capabilities.push('Advanced Queries');
288
516
  if (metadata.capabilities.realtime) capabilities.push('Realtime');
289
517
  if (metadata.capabilities.transactions) capabilities.push('Transactions');
290
-
518
+
291
519
  return {
292
520
  apiMode: metadata.apiMode,
293
521
  terminology: metadata.terminology,