@njdamstra/appwrite-utils-cli 1.8.9 → 1.10.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 (284) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/CONFIG_TODO.md +1189 -0
  3. package/SELECTION_DIALOGS.md +146 -0
  4. package/SERVICE_IMPLEMENTATION_REPORT.md +462 -0
  5. package/dist/adapters/index.d.ts +7 -8
  6. package/dist/adapters/index.js +7 -9
  7. package/dist/backups/operations/bucketBackup.js +2 -2
  8. package/dist/backups/operations/collectionBackup.d.ts +1 -1
  9. package/dist/backups/operations/collectionBackup.js +3 -3
  10. package/dist/backups/operations/comprehensiveBackup.d.ts +1 -1
  11. package/dist/backups/operations/comprehensiveBackup.js +2 -2
  12. package/dist/backups/tracking/centralizedTracking.d.ts +1 -1
  13. package/dist/backups/tracking/centralizedTracking.js +2 -2
  14. package/dist/cli/commands/configCommands.js +51 -7
  15. package/dist/cli/commands/databaseCommands.d.ts +1 -0
  16. package/dist/cli/commands/databaseCommands.js +119 -9
  17. package/dist/cli/commands/functionCommands.js +3 -3
  18. package/dist/cli/commands/importFileCommands.d.ts +7 -0
  19. package/dist/cli/commands/importFileCommands.js +674 -0
  20. package/dist/cli/commands/schemaCommands.js +3 -3
  21. package/dist/cli/commands/storageCommands.js +2 -3
  22. package/dist/cli/commands/transferCommands.js +3 -5
  23. package/dist/collections/attributes.d.ts +1 -1
  24. package/dist/collections/attributes.js +2 -35
  25. package/dist/collections/indexes.js +1 -3
  26. package/dist/collections/methods.d.ts +1 -1
  27. package/dist/collections/methods.js +111 -192
  28. package/dist/collections/tableOperations.d.ts +1 -0
  29. package/dist/collections/tableOperations.js +55 -23
  30. package/dist/collections/transferOperations.d.ts +1 -1
  31. package/dist/collections/transferOperations.js +3 -4
  32. package/dist/collections/wipeOperations.d.ts +4 -3
  33. package/dist/collections/wipeOperations.js +112 -39
  34. package/dist/databases/methods.js +2 -2
  35. package/dist/databases/setup.js +2 -2
  36. package/dist/examples/yamlTerminologyExample.js +2 -2
  37. package/dist/functions/deployments.d.ts +1 -1
  38. package/dist/functions/deployments.js +5 -5
  39. package/dist/functions/fnConfigDiscovery.js +2 -2
  40. package/dist/functions/methods.js +16 -4
  41. package/dist/init.js +1 -1
  42. package/dist/interactiveCLI.d.ts +6 -1
  43. package/dist/interactiveCLI.js +63 -9
  44. package/dist/main.js +130 -177
  45. package/dist/migrations/afterImportActions.js +2 -3
  46. package/dist/migrations/appwriteToX.d.ts +1 -1
  47. package/dist/migrations/appwriteToX.js +9 -7
  48. package/dist/migrations/comprehensiveTransfer.js +3 -5
  49. package/dist/migrations/dataLoader.js +2 -5
  50. package/dist/migrations/importController.js +3 -4
  51. package/dist/migrations/importDataActions.js +3 -3
  52. package/dist/migrations/relationships.js +1 -2
  53. package/dist/migrations/services/DataTransformationService.js +2 -2
  54. package/dist/migrations/services/FileHandlerService.js +1 -1
  55. package/dist/migrations/services/ImportOrchestrator.js +4 -4
  56. package/dist/migrations/services/RateLimitManager.js +1 -1
  57. package/dist/migrations/services/RelationshipResolver.js +1 -1
  58. package/dist/migrations/services/UserMappingService.js +1 -1
  59. package/dist/migrations/services/ValidationService.js +1 -1
  60. package/dist/migrations/transfer.d.ts +8 -4
  61. package/dist/migrations/transfer.js +106 -55
  62. package/dist/migrations/yaml/YamlImportConfigLoader.js +1 -1
  63. package/dist/migrations/yaml/YamlImportIntegration.js +2 -2
  64. package/dist/migrations/yaml/generateImportSchemas.js +1 -1
  65. package/dist/setupCommands.d.ts +1 -1
  66. package/dist/setupCommands.js +5 -6
  67. package/dist/setupController.js +1 -1
  68. package/dist/shared/backupTracking.d.ts +1 -1
  69. package/dist/shared/backupTracking.js +2 -2
  70. package/dist/shared/confirmationDialogs.js +1 -1
  71. package/dist/shared/migrationHelpers.d.ts +1 -1
  72. package/dist/shared/migrationHelpers.js +3 -3
  73. package/dist/shared/operationQueue.d.ts +1 -1
  74. package/dist/shared/operationQueue.js +2 -3
  75. package/dist/shared/operationsTable.d.ts +1 -1
  76. package/dist/shared/operationsTable.js +2 -2
  77. package/dist/shared/progressManager.js +1 -1
  78. package/dist/shared/selectionDialogs.js +9 -8
  79. package/dist/storage/methods.js +4 -4
  80. package/dist/storage/schemas.d.ts +2 -2
  81. package/dist/tables/indexManager.d.ts +65 -0
  82. package/dist/tables/indexManager.js +294 -0
  83. package/dist/types.d.ts +2 -2
  84. package/dist/types.js +1 -1
  85. package/dist/users/methods.js +2 -3
  86. package/dist/utils/configMigration.js +1 -1
  87. package/dist/utils/index.d.ts +1 -1
  88. package/dist/utils/index.js +1 -1
  89. package/dist/utils/loadConfigs.d.ts +2 -2
  90. package/dist/utils/loadConfigs.js +6 -7
  91. package/dist/utils/setupFiles.js +5 -7
  92. package/dist/utilsController.d.ts +15 -8
  93. package/dist/utilsController.js +57 -28
  94. package/package.json +7 -3
  95. package/src/adapters/index.ts +8 -34
  96. package/src/backups/operations/bucketBackup.ts +2 -2
  97. package/src/backups/operations/collectionBackup.ts +4 -4
  98. package/src/backups/operations/comprehensiveBackup.ts +3 -3
  99. package/src/backups/tracking/centralizedTracking.ts +3 -3
  100. package/src/cli/commands/configCommands.ts +72 -8
  101. package/src/cli/commands/databaseCommands.ts +161 -9
  102. package/src/cli/commands/functionCommands.ts +4 -3
  103. package/src/cli/commands/importFileCommands.ts +815 -0
  104. package/src/cli/commands/schemaCommands.ts +3 -3
  105. package/src/cli/commands/storageCommands.ts +2 -3
  106. package/src/cli/commands/transferCommands.ts +3 -6
  107. package/src/collections/attributes.ts +3 -39
  108. package/src/collections/indexes.ts +2 -4
  109. package/src/collections/methods.ts +115 -150
  110. package/src/collections/tableOperations.ts +57 -21
  111. package/src/collections/transferOperations.ts +4 -5
  112. package/src/collections/wipeOperations.ts +154 -51
  113. package/src/databases/methods.ts +2 -2
  114. package/src/databases/setup.ts +2 -2
  115. package/src/examples/yamlTerminologyExample.ts +2 -2
  116. package/src/functions/deployments.ts +6 -5
  117. package/src/functions/fnConfigDiscovery.ts +2 -2
  118. package/src/functions/methods.ts +17 -4
  119. package/src/init.ts +1 -1
  120. package/src/interactiveCLI.ts +75 -10
  121. package/src/main.ts +143 -287
  122. package/src/migrations/afterImportActions.ts +2 -3
  123. package/src/migrations/appwriteToX.ts +12 -8
  124. package/src/migrations/comprehensiveTransfer.ts +6 -6
  125. package/src/migrations/dataLoader.ts +2 -5
  126. package/src/migrations/importController.ts +3 -4
  127. package/src/migrations/importDataActions.ts +3 -3
  128. package/src/migrations/relationships.ts +1 -2
  129. package/src/migrations/services/DataTransformationService.ts +2 -2
  130. package/src/migrations/services/FileHandlerService.ts +1 -1
  131. package/src/migrations/services/ImportOrchestrator.ts +4 -4
  132. package/src/migrations/services/RateLimitManager.ts +1 -1
  133. package/src/migrations/services/RelationshipResolver.ts +1 -1
  134. package/src/migrations/services/UserMappingService.ts +1 -1
  135. package/src/migrations/services/ValidationService.ts +1 -1
  136. package/src/migrations/transfer.ts +126 -83
  137. package/src/migrations/yaml/YamlImportConfigLoader.ts +1 -1
  138. package/src/migrations/yaml/YamlImportIntegration.ts +2 -2
  139. package/src/migrations/yaml/generateImportSchemas.ts +1 -1
  140. package/src/setupCommands.ts +5 -6
  141. package/src/setupController.ts +1 -1
  142. package/src/shared/backupTracking.ts +3 -3
  143. package/src/shared/confirmationDialogs.ts +1 -1
  144. package/src/shared/migrationHelpers.ts +4 -4
  145. package/src/shared/operationQueue.ts +3 -4
  146. package/src/shared/operationsTable.ts +3 -3
  147. package/src/shared/progressManager.ts +1 -1
  148. package/src/shared/selectionDialogs.ts +9 -8
  149. package/src/storage/methods.ts +4 -4
  150. package/src/tables/indexManager.ts +409 -0
  151. package/src/types.ts +2 -2
  152. package/src/users/methods.ts +2 -3
  153. package/src/utils/configMigration.ts +1 -1
  154. package/src/utils/index.ts +1 -1
  155. package/src/utils/loadConfigs.ts +15 -7
  156. package/src/utils/setupFiles.ts +5 -7
  157. package/src/utilsController.ts +86 -32
  158. package/dist/adapters/AdapterFactory.d.ts +0 -94
  159. package/dist/adapters/AdapterFactory.js +0 -405
  160. package/dist/adapters/DatabaseAdapter.d.ts +0 -233
  161. package/dist/adapters/DatabaseAdapter.js +0 -50
  162. package/dist/adapters/LegacyAdapter.d.ts +0 -50
  163. package/dist/adapters/LegacyAdapter.js +0 -612
  164. package/dist/adapters/TablesDBAdapter.d.ts +0 -45
  165. package/dist/adapters/TablesDBAdapter.js +0 -571
  166. package/dist/config/ConfigManager.d.ts +0 -445
  167. package/dist/config/ConfigManager.js +0 -625
  168. package/dist/config/configMigration.d.ts +0 -87
  169. package/dist/config/configMigration.js +0 -390
  170. package/dist/config/configValidation.d.ts +0 -66
  171. package/dist/config/configValidation.js +0 -358
  172. package/dist/config/index.d.ts +0 -8
  173. package/dist/config/index.js +0 -7
  174. package/dist/config/services/ConfigDiscoveryService.d.ts +0 -126
  175. package/dist/config/services/ConfigDiscoveryService.js +0 -374
  176. package/dist/config/services/ConfigLoaderService.d.ts +0 -129
  177. package/dist/config/services/ConfigLoaderService.js +0 -540
  178. package/dist/config/services/ConfigMergeService.d.ts +0 -208
  179. package/dist/config/services/ConfigMergeService.js +0 -308
  180. package/dist/config/services/ConfigValidationService.d.ts +0 -214
  181. package/dist/config/services/ConfigValidationService.js +0 -310
  182. package/dist/config/services/SessionAuthService.d.ts +0 -225
  183. package/dist/config/services/SessionAuthService.js +0 -456
  184. package/dist/config/services/__tests__/ConfigMergeService.test.d.ts +0 -1
  185. package/dist/config/services/__tests__/ConfigMergeService.test.js +0 -271
  186. package/dist/config/services/index.d.ts +0 -13
  187. package/dist/config/services/index.js +0 -10
  188. package/dist/config/yamlConfig.d.ts +0 -722
  189. package/dist/config/yamlConfig.js +0 -702
  190. package/dist/functions/pathResolution.d.ts +0 -37
  191. package/dist/functions/pathResolution.js +0 -185
  192. package/dist/shared/attributeMapper.d.ts +0 -20
  193. package/dist/shared/attributeMapper.js +0 -203
  194. package/dist/shared/errorUtils.d.ts +0 -54
  195. package/dist/shared/errorUtils.js +0 -95
  196. package/dist/shared/functionManager.d.ts +0 -48
  197. package/dist/shared/functionManager.js +0 -336
  198. package/dist/shared/indexManager.d.ts +0 -24
  199. package/dist/shared/indexManager.js +0 -151
  200. package/dist/shared/jsonSchemaGenerator.d.ts +0 -50
  201. package/dist/shared/jsonSchemaGenerator.js +0 -290
  202. package/dist/shared/logging.d.ts +0 -61
  203. package/dist/shared/logging.js +0 -116
  204. package/dist/shared/messageFormatter.d.ts +0 -39
  205. package/dist/shared/messageFormatter.js +0 -162
  206. package/dist/shared/pydanticModelGenerator.d.ts +0 -17
  207. package/dist/shared/pydanticModelGenerator.js +0 -615
  208. package/dist/shared/schemaGenerator.d.ts +0 -40
  209. package/dist/shared/schemaGenerator.js +0 -556
  210. package/dist/utils/ClientFactory.d.ts +0 -87
  211. package/dist/utils/ClientFactory.js +0 -212
  212. package/dist/utils/configDiscovery.d.ts +0 -78
  213. package/dist/utils/configDiscovery.js +0 -472
  214. package/dist/utils/constantsGenerator.d.ts +0 -31
  215. package/dist/utils/constantsGenerator.js +0 -321
  216. package/dist/utils/dataConverters.d.ts +0 -46
  217. package/dist/utils/dataConverters.js +0 -139
  218. package/dist/utils/directoryUtils.d.ts +0 -22
  219. package/dist/utils/directoryUtils.js +0 -59
  220. package/dist/utils/getClientFromConfig.d.ts +0 -39
  221. package/dist/utils/getClientFromConfig.js +0 -199
  222. package/dist/utils/helperFunctions.d.ts +0 -63
  223. package/dist/utils/helperFunctions.js +0 -156
  224. package/dist/utils/pathResolvers.d.ts +0 -53
  225. package/dist/utils/pathResolvers.js +0 -72
  226. package/dist/utils/projectConfig.d.ts +0 -119
  227. package/dist/utils/projectConfig.js +0 -171
  228. package/dist/utils/retryFailedPromises.d.ts +0 -2
  229. package/dist/utils/retryFailedPromises.js +0 -23
  230. package/dist/utils/sessionAuth.d.ts +0 -48
  231. package/dist/utils/sessionAuth.js +0 -164
  232. package/dist/utils/typeGuards.d.ts +0 -35
  233. package/dist/utils/typeGuards.js +0 -57
  234. package/dist/utils/validationRules.d.ts +0 -43
  235. package/dist/utils/validationRules.js +0 -42
  236. package/dist/utils/versionDetection.d.ts +0 -58
  237. package/dist/utils/versionDetection.js +0 -251
  238. package/dist/utils/yamlConverter.d.ts +0 -100
  239. package/dist/utils/yamlConverter.js +0 -428
  240. package/dist/utils/yamlLoader.d.ts +0 -70
  241. package/dist/utils/yamlLoader.js +0 -267
  242. package/src/adapters/AdapterFactory.ts +0 -510
  243. package/src/adapters/DatabaseAdapter.ts +0 -306
  244. package/src/adapters/LegacyAdapter.ts +0 -841
  245. package/src/adapters/TablesDBAdapter.ts +0 -773
  246. package/src/config/ConfigManager.ts +0 -808
  247. package/src/config/README.md +0 -274
  248. package/src/config/configMigration.ts +0 -575
  249. package/src/config/configValidation.ts +0 -445
  250. package/src/config/index.ts +0 -10
  251. package/src/config/services/ConfigDiscoveryService.ts +0 -463
  252. package/src/config/services/ConfigLoaderService.ts +0 -740
  253. package/src/config/services/ConfigMergeService.ts +0 -388
  254. package/src/config/services/ConfigValidationService.ts +0 -394
  255. package/src/config/services/SessionAuthService.ts +0 -565
  256. package/src/config/services/__tests__/ConfigMergeService.test.ts +0 -351
  257. package/src/config/services/index.ts +0 -29
  258. package/src/config/yamlConfig.ts +0 -761
  259. package/src/functions/pathResolution.ts +0 -227
  260. package/src/shared/attributeMapper.ts +0 -229
  261. package/src/shared/errorUtils.ts +0 -110
  262. package/src/shared/functionManager.ts +0 -525
  263. package/src/shared/indexManager.ts +0 -254
  264. package/src/shared/jsonSchemaGenerator.ts +0 -383
  265. package/src/shared/logging.ts +0 -149
  266. package/src/shared/messageFormatter.ts +0 -208
  267. package/src/shared/pydanticModelGenerator.ts +0 -618
  268. package/src/shared/schemaGenerator.ts +0 -644
  269. package/src/utils/ClientFactory.ts +0 -240
  270. package/src/utils/configDiscovery.ts +0 -557
  271. package/src/utils/constantsGenerator.ts +0 -369
  272. package/src/utils/dataConverters.ts +0 -159
  273. package/src/utils/directoryUtils.ts +0 -61
  274. package/src/utils/getClientFromConfig.ts +0 -257
  275. package/src/utils/helperFunctions.ts +0 -228
  276. package/src/utils/pathResolvers.ts +0 -81
  277. package/src/utils/projectConfig.ts +0 -299
  278. package/src/utils/retryFailedPromises.ts +0 -29
  279. package/src/utils/sessionAuth.ts +0 -230
  280. package/src/utils/typeGuards.ts +0 -65
  281. package/src/utils/validationRules.ts +0 -88
  282. package/src/utils/versionDetection.ts +0 -292
  283. package/src/utils/yamlConverter.ts +0 -542
  284. package/src/utils/yamlLoader.ts +0 -371
@@ -12,9 +12,8 @@ import { join } from "node:path";
12
12
  import path from "path";
13
13
  import fs from "node:fs";
14
14
  import os from "node:os";
15
- import { MessageFormatter } from "./shared/messageFormatter.js";
15
+ import { MessageFormatter, findYamlConfig } from "@njdamstra/appwrite-utils-helpers";
16
16
  import { findAppwriteConfig } from "./utils/loadConfigs.js";
17
- import { findYamlConfig } from "./config/yamlConfig.js";
18
17
  // Import command modules
19
18
  import { configCommands } from "./cli/commands/configCommands.js";
20
19
  import { databaseCommands } from "./cli/commands/databaseCommands.js";
@@ -22,6 +21,7 @@ import { functionCommands } from "./cli/commands/functionCommands.js";
22
21
  import { storageCommands } from "./cli/commands/storageCommands.js";
23
22
  import { transferCommands } from "./cli/commands/transferCommands.js";
24
23
  import { schemaCommands } from "./cli/commands/schemaCommands.js";
24
+ import { importFileCommands } from "./cli/commands/importFileCommands.js";
25
25
  var CHOICES;
26
26
  (function (CHOICES) {
27
27
  CHOICES["MIGRATE_CONFIG"] = "\uD83D\uDD04 Migrate TypeScript config to YAML (.appwrite structure)";
@@ -43,6 +43,7 @@ var CHOICES;
43
43
  CHOICES["GENERATE_SCHEMAS"] = "\uD83C\uDFD7\uFE0F Generate schemas";
44
44
  CHOICES["GENERATE_CONSTANTS"] = "\uD83D\uDCCB Generate cross-language constants (TypeScript, Python, PHP, Dart, etc.)";
45
45
  CHOICES["IMPORT_DATA"] = "\uD83D\uDCE5 Import data";
46
+ CHOICES["IMPORT_FILE"] = "\uD83D\uDCC4 Import file (CSV/JSON) directly into a table";
46
47
  CHOICES["RELOAD_CONFIG"] = "\uD83D\uDD04 Reload configuration files";
47
48
  CHOICES["UPDATE_FUNCTION_SPEC"] = "\u2699\uFE0F Update function specifications";
48
49
  CHOICES["MANAGE_BUCKETS"] = "\uD83E\uDEA3 Manage storage buckets";
@@ -53,12 +54,14 @@ export class InteractiveCLI {
53
54
  controller;
54
55
  isUsingTypeScriptConfig = false;
55
56
  lastSelectedCollectionIds = [];
56
- constructor(currentDir) {
57
+ options;
58
+ constructor(currentDir, options = {}) {
57
59
  this.currentDir = currentDir;
60
+ this.options = options;
58
61
  }
59
62
  async run() {
60
63
  MessageFormatter.banner("Appwrite Utils CLI", "Welcome to Appwrite Utils CLI Tool by Zach Handley");
61
- MessageFormatter.info("For more information, visit https://github.com/zachhandley/AppwriteUtils");
64
+ MessageFormatter.info("For more information, visit https://github.com/njdamstra/AppwriteUtils");
62
65
  // Detect configuration type
63
66
  try {
64
67
  await this.detectConfigurationType();
@@ -148,6 +151,10 @@ export class InteractiveCLI {
148
151
  await this.initControllerIfNeeded();
149
152
  await schemaCommands.importData(this);
150
153
  break;
154
+ case CHOICES.IMPORT_FILE:
155
+ await this.initControllerIfNeeded();
156
+ await importFileCommands.importFile(this);
157
+ break;
151
158
  case CHOICES.RELOAD_CONFIG:
152
159
  await configCommands.reloadConfigWithSessionPreservation(this);
153
160
  break;
@@ -167,7 +174,10 @@ export class InteractiveCLI {
167
174
  async initControllerIfNeeded(directConfig) {
168
175
  if (!this.controller) {
169
176
  this.controller = UtilsController.getInstance(this.currentDir, directConfig);
170
- await this.controller.init();
177
+ await this.controller.init({
178
+ useSession: this.options.useSession,
179
+ sessionCookie: this.options.sessionCookie
180
+ });
171
181
  }
172
182
  else {
173
183
  // Extract session info from existing controller before reinitializing
@@ -182,13 +192,19 @@ export class InteractiveCLI {
182
192
  // Reinitialize with session preservation
183
193
  UtilsController.clearInstance();
184
194
  this.controller = UtilsController.getInstance(this.currentDir, enhancedDirectConfig);
185
- await this.controller.init();
195
+ await this.controller.init({
196
+ useSession: this.options.useSession,
197
+ sessionCookie: this.options.sessionCookie
198
+ });
186
199
  }
187
200
  else if (directConfig) {
188
201
  // Standard reinitialize without session
189
202
  UtilsController.clearInstance();
190
203
  this.controller = UtilsController.getInstance(this.currentDir, directConfig);
191
- await this.controller.init();
204
+ await this.controller.init({
205
+ useSession: this.options.useSession,
206
+ sessionCookie: this.options.sessionCookie
207
+ });
192
208
  }
193
209
  // If no directConfig provided, keep existing controller
194
210
  }
@@ -258,7 +274,8 @@ export class InteractiveCLI {
258
274
  pageSize: 10,
259
275
  },
260
276
  ]);
261
- return selectedDatabases;
277
+ // "list" type returns a single value, "checkbox" returns an array — normalize to array
278
+ return Array.isArray(selectedDatabases) ? selectedDatabases : [selectedDatabases];
262
279
  }
263
280
  async selectCollections(database, databasesClient, message, multiSelect = true, preferLocal = false, shouldFilterByDatabase = false) {
264
281
  await this.initControllerIfNeeded();
@@ -299,6 +316,9 @@ export class InteractiveCLI {
299
316
  allCollections = allCollections.filter((collection) => !collection.$id.startsWith('_'));
300
317
  const hasLocalAndRemote = allCollections.some((coll) => configCollections.some((c) => c.name === coll.name || c.$id === coll.$id)) &&
301
318
  allCollections.some((coll) => !configCollections.some((c) => c.name === coll.name || c.$id === coll.$id));
319
+ const getCollectionId = (collection) => collection.$id || collection.name;
320
+ const localCollectionIds = new Set(configCollections.map((c) => c.$id || c.name));
321
+ const localCollections = allCollections.filter((collection) => localCollectionIds.has(getCollectionId(collection)));
302
322
  // Enhanced choice display with type indicators
303
323
  const choices = allCollections
304
324
  .sort((a, b) => {
@@ -349,6 +369,18 @@ export class InteractiveCLI {
349
369
  value: collection,
350
370
  };
351
371
  });
372
+ if (multiSelect && localCollections.length > 1) {
373
+ choices.unshift({
374
+ name: chalk.green.bold(`📋 Select All Local Items (${localCollections.length})`),
375
+ value: "__SELECT_ALL_LOCAL__"
376
+ });
377
+ }
378
+ if (multiSelect && allCollections.length > 1) {
379
+ choices.unshift({
380
+ name: chalk.green.bold(`📋 Select All Shown (${allCollections.length})`),
381
+ value: "__SELECT_ALL__"
382
+ });
383
+ }
352
384
  const { selectedCollections } = await inquirer.prompt([
353
385
  {
354
386
  type: multiSelect ? "checkbox" : "list",
@@ -357,8 +389,27 @@ export class InteractiveCLI {
357
389
  choices,
358
390
  loop: true,
359
391
  pageSize: 15, // Increased page size to accommodate additional info
392
+ validate: (input) => {
393
+ if (!multiSelect)
394
+ return true;
395
+ if (input.includes("__SELECT_ALL__") && input.length > 1) {
396
+ return "Cannot select 'Select All' with individual items.";
397
+ }
398
+ if (input.includes("__SELECT_ALL_LOCAL__") && input.length > 1) {
399
+ return "Cannot select 'Select All Local' with individual items.";
400
+ }
401
+ return true;
402
+ }
360
403
  },
361
404
  ]);
405
+ if (multiSelect && Array.isArray(selectedCollections)) {
406
+ if (selectedCollections.includes("__SELECT_ALL__")) {
407
+ return allCollections;
408
+ }
409
+ if (selectedCollections.includes("__SELECT_ALL_LOCAL__")) {
410
+ return localCollections;
411
+ }
412
+ }
362
413
  return selectedCollections;
363
414
  }
364
415
  /**
@@ -800,7 +851,10 @@ export class InteractiveCLI {
800
851
  }, bucketId.length > 0 ? bucketId : ulid());
801
852
  }
802
853
  getLocalCollections() {
803
- const configCollections = this.controller.config?.collections || [];
854
+ const configCollections = [
855
+ ...(this.controller.config?.collections || []),
856
+ ...(this.controller.config?.tables || [])
857
+ ];
804
858
  // @ts-expect-error - appwrite invalid types
805
859
  return configCollections.map((c) => ({
806
860
  $id: c.$id || ulid(),
package/dist/main.js CHANGED
@@ -5,22 +5,18 @@ import { hideBin } from "yargs/helpers";
5
5
  import { InteractiveCLI } from "./interactiveCLI.js";
6
6
  import { UtilsController } from "./utilsController.js";
7
7
  import { Databases, Storage } from "node-appwrite";
8
- import { getClient } from "./utils/getClientFromConfig.js";
8
+ import { getClient } from "@njdamstra/appwrite-utils-helpers";
9
9
  import { fetchAllDatabases } from "./databases/methods.js";
10
10
  import { setupDirsFiles } from "./utils/setupFiles.js";
11
11
  import { fetchAllCollections } from "./collections/methods.js";
12
12
  import chalk from "chalk";
13
13
  import { listSpecifications } from "./functions/methods.js";
14
- import { MessageFormatter } from "./shared/messageFormatter.js";
14
+ import { MessageFormatter, logger, AuthenticationError } from "@njdamstra/appwrite-utils-helpers";
15
15
  import { ConfirmationDialogs } from "./shared/confirmationDialogs.js";
16
16
  import { SelectionDialogs } from "./shared/selectionDialogs.js";
17
- import { logger } from "./shared/logging.js";
18
17
  import path from "path";
19
18
  import fs from "fs";
20
19
  import { createRequire } from "node:module";
21
- import { loadAppwriteProjectConfig, findAppwriteProjectConfig, projectConfigToAppwriteConfig, } from "./utils/projectConfig.js";
22
- import { hasSessionAuth, getAvailableSessions, getAuthenticationStatus, } from "./utils/sessionAuth.js";
23
- import { findYamlConfig, loadYamlConfigWithSession, } from "./config/yamlConfig.js";
24
20
  const require = createRequire(import.meta.url);
25
21
  if (!globalThis.require) {
26
22
  globalThis.require = require;
@@ -217,6 +213,11 @@ const argv = yargs(hideBin(process.argv))
217
213
  .option("config", {
218
214
  type: "string",
219
215
  description: "Path to Appwrite configuration file (appwriteConfig.ts)",
216
+ })
217
+ .option("appwriteConfig", {
218
+ alias: ["appwrite-config", "use-appwrite-config"],
219
+ type: "boolean",
220
+ description: "Prefer loading from appwrite.config.json instead of config.yaml",
220
221
  })
221
222
  .option("it", {
222
223
  alias: ["interactive", "i"],
@@ -438,134 +439,85 @@ const argv = yargs(hideBin(process.argv))
438
439
  .option("sessionCookie", {
439
440
  type: "string",
440
441
  description: "Explicit session cookie to use for authentication",
442
+ })
443
+ .option("importFile", {
444
+ alias: ["import-file"],
445
+ type: "string",
446
+ description: "Import a CSV or JSON file directly into a table (no config needed)",
447
+ })
448
+ .option("targetDb", {
449
+ alias: ["target-db"],
450
+ type: "string",
451
+ description: "Target database ID for --importFile (prompted if omitted)",
452
+ })
453
+ .option("targetTable", {
454
+ alias: ["target-table"],
455
+ type: "string",
456
+ description: "Target table ID for --importFile (prompted if omitted)",
441
457
  })
442
458
  .parse();
443
459
  async function main() {
444
460
  const startTime = Date.now();
445
461
  const operationStats = {};
446
- // Early session detection for better user guidance
447
- const availableSessions = getAvailableSessions();
448
- let hasAnyValidSessions = availableSessions.length > 0;
449
462
  if (argv.it) {
450
- const cli = new InteractiveCLI(process.cwd());
463
+ const cli = new InteractiveCLI(process.cwd(), {
464
+ useSession: argv.useSession,
465
+ sessionCookie: argv.sessionCookie
466
+ });
451
467
  await cli.run();
452
468
  }
453
469
  else {
454
- // Enhanced config creation with session and project file support
455
- let directConfig = undefined;
456
- // Show authentication status on startup if no config provided
457
- if (!argv.config &&
458
- !argv.endpoint &&
459
- !argv.projectId &&
460
- !argv.apiKey &&
461
- !argv.useSession &&
462
- !argv.sessionCookie) {
463
- if (hasAnyValidSessions) {
464
- MessageFormatter.info(`Found ${availableSessions.length} available session(s)`, { prefix: "Auth" });
465
- availableSessions.forEach((session) => {
466
- MessageFormatter.info(` \u2022 ${session.projectId} (${session.email || "unknown"}) at ${session.endpoint}`, { prefix: "Auth" });
467
- });
468
- MessageFormatter.info("Use --session to enable session authentication", { prefix: "Auth" });
469
- }
470
- else {
471
- MessageFormatter.info("No active Appwrite sessions found", {
472
- prefix: "Auth",
473
- });
474
- MessageFormatter.info("\u2022 Run 'appwrite login' to authenticate with session", { prefix: "Auth" });
475
- MessageFormatter.info("\u2022 Or provide --apiKey for API key authentication", { prefix: "Auth" });
476
- }
477
- }
478
- // Priority 1: Check for appwrite.json project configuration
479
- const projectConfigPath = findAppwriteProjectConfig(process.cwd());
480
- if (projectConfigPath) {
481
- const projectConfig = loadAppwriteProjectConfig(projectConfigPath);
482
- if (projectConfig) {
483
- directConfig = projectConfigToAppwriteConfig(projectConfig);
484
- MessageFormatter.info(`Loaded project configuration from ${projectConfigPath}`, { prefix: "CLI" });
485
- }
486
- }
487
- // Priority 2: CLI arguments override project config
488
- if (argv.endpoint ||
489
- argv.projectId ||
490
- argv.apiKey ||
491
- argv.useSession ||
492
- argv.sessionCookie) {
493
- directConfig = {
494
- ...directConfig,
495
- appwriteEndpoint: argv.endpoint || directConfig?.appwriteEndpoint,
496
- appwriteProject: argv.projectId || directConfig?.appwriteProject,
497
- appwriteKey: argv.apiKey || directConfig?.appwriteKey,
470
+ // Non-interactive mode - pass auth flags through to controller
471
+ // ConfigManager will handle config discovery and auth decisions
472
+ // Users can provide credentials via CLI flags even without a config file
473
+ const controller = UtilsController.getInstance(process.cwd());
474
+ // Build init options from CLI flags
475
+ const initOptions = {
476
+ useSession: argv.useSession,
477
+ sessionCookie: argv.sessionCookie,
478
+ preferJson: argv.appwriteConfig,
479
+ };
480
+ // Add CLI overrides if provided - these can work even without a config file
481
+ if (argv.endpoint || argv.projectId || argv.apiKey) {
482
+ initOptions.overrides = {
483
+ appwriteEndpoint: argv.endpoint,
484
+ appwriteProject: argv.projectId,
485
+ appwriteKey: argv.apiKey,
498
486
  };
499
487
  }
500
- // Priority 3: Session authentication support with improved detection
501
- let sessionAuthAvailable = false;
502
- if (directConfig?.appwriteEndpoint && directConfig?.appwriteProject) {
503
- sessionAuthAvailable = hasSessionAuth(directConfig.appwriteEndpoint, directConfig.appwriteProject);
488
+ try {
489
+ await controller.init(initOptions);
504
490
  }
505
- if (argv.useSession || argv.sessionCookie) {
506
- if (argv.sessionCookie) {
507
- // Explicit session cookie provided
508
- MessageFormatter.info("Using explicit session cookie for authentication", { prefix: "Auth" });
509
- }
510
- else if (sessionAuthAvailable) {
511
- MessageFormatter.info("Session authentication detected and will be used", { prefix: "Auth" });
512
- }
513
- else {
514
- MessageFormatter.warning("Session authentication requested but no valid session found", { prefix: "Auth" });
515
- const availableSessions = getAvailableSessions();
516
- if (availableSessions.length > 0) {
517
- MessageFormatter.info(`Available sessions: ${availableSessions
518
- .map((s) => `${s.projectId} (${s.email || "unknown"})`)
519
- .join(", ")}`, { prefix: "Auth" });
520
- MessageFormatter.info("Use --session flag to enable session authentication", { prefix: "Auth" });
521
- }
522
- else {
523
- MessageFormatter.warning("No Appwrite CLI sessions found. Please run 'appwrite login' first.", { prefix: "Auth" });
524
- }
525
- MessageFormatter.error("Session authentication requested but not available", undefined, { prefix: "Auth" });
526
- return; // Exit early if session auth was requested but not available
491
+ catch (error) {
492
+ if (error instanceof AuthenticationError) {
493
+ MessageFormatter.error(error.getFormattedMessage(), undefined, { prefix: "Auth" });
494
+ process.exit(1);
527
495
  }
496
+ // Re-throw other errors
497
+ throw error;
528
498
  }
529
- else if (sessionAuthAvailable && !argv.apiKey) {
530
- // Auto-detect session authentication when no API key is provided
531
- MessageFormatter.info("Session authentication detected - no API key required", { prefix: "Auth" });
532
- MessageFormatter.info("Use --session flag to explicitly enable session authentication", { prefix: "Auth" });
533
- }
534
- // Enhanced session authentication support:
535
- // 1. If session auth is explicitly requested via flags, use it
536
- // 2. If no API key is provided but sessions are available, offer to use session auth
537
- // 3. Auto-detect session authentication when possible
538
- let finalDirectConfig = directConfig;
539
- if ((argv.useSession || argv.sessionCookie) &&
540
- (!directConfig ||
541
- !directConfig.appwriteEndpoint ||
542
- !directConfig.appwriteProject)) {
543
- // Don't pass incomplete directConfig - let UtilsController load YAML config normally
544
- finalDirectConfig = null;
499
+ // After init, check if we have a valid config (from file OR CLI overrides)
500
+ if (!controller.config) {
501
+ MessageFormatter.error("No Appwrite configuration available", undefined, { prefix: "CLI" });
502
+ MessageFormatter.info("Provide credentials via CLI flags (--endpoint, --projectId, --apiKey or --session)", { prefix: "CLI" });
503
+ MessageFormatter.info("Or create a config file using --setup", { prefix: "CLI" });
504
+ return;
545
505
  }
546
- else if (finalDirectConfig &&
547
- !finalDirectConfig.appwriteKey &&
548
- !argv.useSession &&
549
- !argv.sessionCookie) {
550
- // Auto-detect session authentication when no API key provided
551
- if (sessionAuthAvailable) {
552
- MessageFormatter.info("No API key provided, but session authentication is available", { prefix: "Auth" });
553
- MessageFormatter.info("Automatically using session authentication (add --session to suppress this message)", { prefix: "Auth" });
554
- // Implicitly enable session authentication
555
- argv.useSession = true;
506
+ const parsedArgv = argv;
507
+ if (argv.importFile) {
508
+ const { importFileFromPath, importFilePromptMissing } = await import("./cli/commands/importFileCommands.js");
509
+ if (!controller.adapter) {
510
+ MessageFormatter.error("No adapter available check your credentials", undefined, { prefix: "Import" });
511
+ return;
556
512
  }
557
- }
558
- // Create controller with session authentication support using singleton
559
- const controller = UtilsController.getInstance(process.cwd(), finalDirectConfig);
560
- // Pass session authentication options to the controller
561
- const initOptions = {};
562
- if (argv.useSession || argv.sessionCookie) {
563
- initOptions.useSession = true;
564
- if (argv.sessionCookie) {
565
- initOptions.sessionCookie = argv.sessionCookie;
513
+ if (parsedArgv.targetDb && parsedArgv.targetTable) {
514
+ await importFileFromPath(controller.adapter, argv.importFile, parsedArgv.targetDb, parsedArgv.targetTable);
515
+ }
516
+ else {
517
+ await importFilePromptMissing(controller.adapter, controller.database, argv.importFile, parsedArgv.targetDb, parsedArgv.targetTable);
566
518
  }
519
+ return;
567
520
  }
568
- await controller.init(initOptions);
569
521
  if (argv.setup) {
570
522
  await setupDirsFiles(false, process.cwd());
571
523
  return;
@@ -576,7 +528,7 @@ async function main() {
576
528
  return;
577
529
  }
578
530
  if (argv.generateConstants) {
579
- const { ConstantsGenerator } = await import("./utils/constantsGenerator.js");
531
+ const { ConstantsGenerator } = await import("@njdamstra/appwrite-utils-helpers");
580
532
  if (!controller.config) {
581
533
  MessageFormatter.error("No Appwrite configuration found", undefined, {
582
534
  prefix: "Constants",
@@ -642,7 +594,7 @@ async function main() {
642
594
  MessageFormatter.info(" • tables/ folder must not exist or be empty", { prefix: "Migration" });
643
595
  return;
644
596
  }
645
- const { migrateCollectionsToTables } = await import("./config/configMigration.js");
597
+ const { migrateCollectionsToTables } = await import("@njdamstra/appwrite-utils-helpers");
646
598
  MessageFormatter.info("Starting collections to tables migration...", {
647
599
  prefix: "Migration",
648
600
  });
@@ -666,41 +618,9 @@ async function main() {
666
618
  }
667
619
  return;
668
620
  }
669
- if (!controller.config) {
670
- // Provide better guidance based on available authentication methods
671
- const availableSessions = getAvailableSessions();
672
- if (availableSessions.length > 0) {
673
- MessageFormatter.error("No Appwrite configuration found", undefined, {
674
- prefix: "CLI",
675
- });
676
- MessageFormatter.info("Available authentication options:", {
677
- prefix: "Auth",
678
- });
679
- MessageFormatter.info("• Session authentication: Add --session flag", {
680
- prefix: "Auth",
681
- });
682
- MessageFormatter.info("• API key authentication: Add --apiKey YOUR_API_KEY", { prefix: "Auth" });
683
- MessageFormatter.info(`• Available sessions: ${availableSessions
684
- .map((s) => `${s.projectId} (${s.email || "unknown"})`)
685
- .join(", ")}`, { prefix: "Auth" });
686
- }
687
- else {
688
- MessageFormatter.error("No Appwrite configuration found", undefined, {
689
- prefix: "CLI",
690
- });
691
- MessageFormatter.info("Authentication options:", { prefix: "Auth" });
692
- MessageFormatter.info("• Login with Appwrite CLI: Run 'appwrite login' then use --session flag", { prefix: "Auth" });
693
- MessageFormatter.info("• Use API key: Add --apiKey YOUR_API_KEY", {
694
- prefix: "Auth",
695
- });
696
- MessageFormatter.info("• Create config file: Run with --setup to initialize project configuration", { prefix: "Auth" });
697
- }
698
- return;
699
- }
700
- const parsedArgv = argv;
701
621
  // List backups if requested
702
622
  if (parsedArgv.listBackups) {
703
- const { AdapterFactory } = await import("./adapters/AdapterFactory.js");
623
+ const { AdapterFactory } = await import("@njdamstra/appwrite-utils-helpers");
704
624
  const { listBackups } = await import("./shared/backupTracking.js");
705
625
  if (!controller.config) {
706
626
  MessageFormatter.error("No Appwrite configuration found", undefined, {
@@ -789,7 +709,7 @@ async function main() {
789
709
  // Comprehensive backup (all databases + all buckets)
790
710
  if (parsedArgv.comprehensiveBackup) {
791
711
  const { comprehensiveBackup } = await import("./backups/operations/comprehensiveBackup.js");
792
- const { AdapterFactory } = await import("./adapters/AdapterFactory.js");
712
+ const { AdapterFactory } = await import("@njdamstra/appwrite-utils-helpers");
793
713
  // Get tracking database ID (interactive prompt if not specified)
794
714
  let trackingDatabaseId = parsedArgv.trackingDatabaseId;
795
715
  if (!trackingDatabaseId) {
@@ -963,7 +883,10 @@ async function main() {
963
883
  }
964
884
  // Build DatabaseSelection[] with tableIds per DB
965
885
  const databaseSelections = [];
966
- const allConfigItems = controller.config.collections || controller.config.tables || [];
886
+ const allConfigItems = [
887
+ ...(controller.config.collections || []),
888
+ ...(controller.config.tables || [])
889
+ ];
967
890
  let lastSelectedTableIds = null;
968
891
  for (const dbId of selectedDbIds) {
969
892
  const db = availableDatabases.find(d => d.$id === dbId);
@@ -979,8 +902,16 @@ async function main() {
979
902
  return one === dbId;
980
903
  return true; // eligible everywhere if unspecified
981
904
  });
982
- // Fetch available tables from remote for selection context
905
+ // Fetch available tables from remote for status/context
983
906
  const availableTables = await fetchAllCollections(dbId, controller.database);
907
+ const remoteTableIds = new Set(availableTables.map(table => table.$id));
908
+ const localItems = eligibleConfigItems;
909
+ const localItemIds = localItems.map(item => item.$id || item.id || item.tableId || item.name);
910
+ const localNewItems = localItems.filter(item => {
911
+ const itemId = item.$id || item.id || item.tableId || item.name;
912
+ return !remoteTableIds.has(itemId);
913
+ });
914
+ const localNewIds = localNewItems.map(item => item.$id || item.id || item.tableId || item.name);
984
915
  // Determine selected table IDs
985
916
  let selectedTableIds = [];
986
917
  if (parsedArgv.collectionIds) {
@@ -988,35 +919,57 @@ async function main() {
988
919
  selectedTableIds = parsedArgv.collectionIds.split(/[\,\s]+/).filter(Boolean);
989
920
  }
990
921
  else {
991
- // If we have a previous selection, offer to reuse it
922
+ const inquirer = (await import("inquirer")).default;
923
+ const choices = [];
992
924
  if (lastSelectedTableIds && lastSelectedTableIds.length > 0) {
993
- const inquirer = (await import("inquirer")).default;
994
- const { reuseMode } = await inquirer.prompt([
995
- {
996
- type: "list",
997
- name: "reuseMode",
998
- message: `How do you want to select tables for ${db.name}?`,
999
- choices: [
1000
- { name: `Use same selection as previous (${lastSelectedTableIds.length} items)`, value: "same" },
1001
- { name: `Filter by this database (manual select)`, value: "filter" },
1002
- { name: `Show all available in this database (manual select)`, value: "all" }
1003
- ],
1004
- default: "same"
1005
- }
1006
- ]);
1007
- if (reuseMode === "same") {
1008
- selectedTableIds = [...lastSelectedTableIds];
925
+ choices.push({
926
+ name: `Use same selection as previous (${lastSelectedTableIds.length} items)`,
927
+ value: "same"
928
+ });
929
+ }
930
+ if (localItemIds.length > 0) {
931
+ choices.push({
932
+ name: `Select all local items for ${db.name} (${localItemIds.length} items)`,
933
+ value: "all_local"
934
+ });
935
+ }
936
+ if (localNewIds.length > 0) {
937
+ choices.push({
938
+ name: `Select only new local items (not on remote) (${localNewIds.length} items)`,
939
+ value: "new_only"
940
+ });
941
+ }
942
+ choices.push({
943
+ name: "Manual selection",
944
+ value: "manual"
945
+ });
946
+ const { selectionMode } = await inquirer.prompt([
947
+ {
948
+ type: "list",
949
+ name: "selectionMode",
950
+ message: `How do you want to select tables for ${db.name}?`,
951
+ choices,
952
+ default: choices[0]?.value || "manual"
1009
953
  }
1010
- else if (reuseMode === "all") {
1011
- selectedTableIds = await SelectionDialogs.selectTablesForDatabase(dbId, db.name, availableTables, allConfigItems, { showSelectAll: false, allowNewOnly: false, defaultSelected: lastSelectedTableIds });
954
+ ]);
955
+ if (selectionMode === "same") {
956
+ selectedTableIds = [...(lastSelectedTableIds || [])];
957
+ }
958
+ else if (selectionMode === "all_local") {
959
+ selectedTableIds = [...localItemIds];
960
+ }
961
+ else if (selectionMode === "new_only") {
962
+ selectedTableIds = [...localNewIds];
963
+ }
964
+ else {
965
+ if (localItems.length === 0) {
966
+ MessageFormatter.warning(`No local tables/collections available for ${db.name}`, { prefix: "Push" });
967
+ selectedTableIds = [];
1012
968
  }
1013
969
  else {
1014
- selectedTableIds = await SelectionDialogs.selectTablesForDatabase(dbId, db.name, availableTables, eligibleConfigItems, { showSelectAll: false, allowNewOnly: true, defaultSelected: lastSelectedTableIds });
970
+ selectedTableIds = await SelectionDialogs.selectTablesForDatabase(dbId, db.name, localItems, availableTables, { showSelectAll: localItems.length > 1, allowNewOnly: false, defaultSelected: lastSelectedTableIds || [] });
1015
971
  }
1016
972
  }
1017
- else {
1018
- selectedTableIds = await SelectionDialogs.selectTablesForDatabase(dbId, db.name, availableTables, eligibleConfigItems, { showSelectAll: false, allowNewOnly: true, defaultSelected: [] });
1019
- }
1020
973
  }
1021
974
  databaseSelections.push({
1022
975
  databaseId: db.$id,
@@ -3,10 +3,9 @@ import { InputFile } from "node-appwrite/file";
3
3
  import path from "path";
4
4
  import fs from "fs";
5
5
  import os from "os";
6
- import { logger } from "../shared/logging.js";
6
+ import { logger, MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
7
7
  import { tryAwaitWithRetry, } from "@njdamstra/appwrite-utils";
8
- import { getClientFromConfig } from "../utils/getClientFromConfig.js";
9
- import { MessageFormatter } from "../shared/messageFormatter.js";
8
+ import { getClientFromConfig } from "@njdamstra/appwrite-utils-helpers";
10
9
  export const getDatabaseFromConfig = (config) => {
11
10
  getClientFromConfig(config); // Sets config.appwriteClient if missing
12
11
  return new Databases(config.appwriteClient);
@@ -1,6 +1,6 @@
1
1
  import { Storage, type Models } from "node-appwrite";
2
2
  import { type AppwriteConfig } from "@njdamstra/appwrite-utils";
3
- import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
3
+ import type { DatabaseAdapter } from "@njdamstra/appwrite-utils-helpers";
4
4
  import type { DatabaseSelection, BucketSelection } from "../shared/selectionDialogs.js";
5
5
  export declare class AppwriteToX {
6
6
  config: AppwriteConfig;
@@ -1,15 +1,14 @@
1
- import { SchemaGenerator } from "../shared/schemaGenerator.js";
2
- import { findYamlConfig } from "../config/yamlConfig.js";
1
+ import { SchemaGenerator, findYamlConfig } from "@njdamstra/appwrite-utils-helpers";
3
2
  import { Client, Compression, Databases, Query, Storage, } from "node-appwrite";
4
3
  import { fetchAllCollections } from "../collections/methods.js";
5
4
  import { fetchAllDatabases } from "../databases/methods.js";
6
5
  import { CollectionSchema, attributeSchema, AppwriteConfigSchema, permissionsSchema, attributesSchema, indexesSchema, parseAttribute, } from "@njdamstra/appwrite-utils";
7
6
  import { getDatabaseFromConfig } from "./afterImportActions.js";
8
- import { getAdapterFromConfig } from "../utils/getClientFromConfig.js";
7
+ import { getAdapterFromConfig } from "@njdamstra/appwrite-utils-helpers";
9
8
  import { listBuckets } from "../storage/methods.js";
10
9
  import { listFunctions, listFunctionDeployments, getFunction } from "../functions/methods.js";
11
- import { MessageFormatter } from "../shared/messageFormatter.js";
12
- import { isLegacyDatabases } from "../utils/typeGuards.js";
10
+ import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
11
+ import { isLegacyDatabases } from "@njdamstra/appwrite-utils-helpers";
13
12
  /**
14
13
  * Convert between collection and table terminology based on data structure
15
14
  */
@@ -80,8 +79,11 @@ export class AppwriteToX {
80
79
  const client = new Client();
81
80
  client
82
81
  .setEndpoint(this.config.appwriteEndpoint)
83
- .setProject(this.config.appwriteProject)
84
- .setKey(this.config.appwriteKey);
82
+ .setProject(this.config.appwriteProject);
83
+ // Only set API key if provided (session auth is alternative)
84
+ if (this.config.appwriteKey) {
85
+ client.setKey(this.config.appwriteKey);
86
+ }
85
87
  this.config.appwriteClient = client;
86
88
  }
87
89
  }