appwrite-utils-cli 1.9.7 → 1.11.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 (425) hide show
  1. package/CONFIG_TODO.md +1189 -1189
  2. package/README.md +1004 -1004
  3. package/SELECTION_DIALOGS.md +145 -145
  4. package/SERVICE_IMPLEMENTATION_REPORT.md +462 -462
  5. package/package.json +6 -3
  6. package/scripts/copy-templates.ts +23 -23
  7. package/src/adapters/index.ts +11 -37
  8. package/src/backups/operations/bucketBackup.ts +277 -277
  9. package/src/backups/operations/collectionBackup.ts +310 -310
  10. package/src/backups/operations/comprehensiveBackup.ts +342 -342
  11. package/src/backups/schemas/bucketManifest.ts +78 -78
  12. package/src/backups/schemas/comprehensiveManifest.ts +76 -76
  13. package/src/backups/tracking/centralizedTracking.ts +352 -352
  14. package/src/cli/commands/configCommands.ts +265 -201
  15. package/src/cli/commands/databaseCommands.ts +931 -879
  16. package/src/cli/commands/functionCommands.ts +333 -332
  17. package/src/cli/commands/importFileCommands.ts +815 -0
  18. package/src/cli/commands/schemaCommands.ts +141 -141
  19. package/src/cli/commands/storageCommands.ts +2 -3
  20. package/src/cli/commands/transferCommands.ts +454 -457
  21. package/src/collections/attributes.ts.backup +1555 -1555
  22. package/src/collections/{attributes.ts → columns.ts} +15 -10
  23. package/src/collections/indexes.ts +350 -352
  24. package/src/collections/methods.ts +714 -700
  25. package/src/collections/tableOperations.ts +29 -8
  26. package/src/collections/transferOperations.ts +376 -377
  27. package/src/collections/wipeOperations.ts +449 -346
  28. package/src/databases/methods.ts +49 -49
  29. package/src/databases/setup.ts +77 -77
  30. package/src/examples/yamlTerminologyExample.ts +346 -346
  31. package/src/functions/deployments.ts +221 -220
  32. package/src/functions/fnConfigDiscovery.ts +2 -2
  33. package/src/functions/methods.ts +284 -284
  34. package/src/functions/templates/count-docs-in-collection/README.md +53 -53
  35. package/src/functions/templates/count-docs-in-collection/src/main.ts +159 -159
  36. package/src/functions/templates/count-docs-in-collection/src/request.ts +8 -8
  37. package/src/functions/templates/hono-typescript/README.md +285 -285
  38. package/src/functions/templates/hono-typescript/src/adapters/request.ts +73 -73
  39. package/src/functions/templates/hono-typescript/src/adapters/response.ts +105 -105
  40. package/src/functions/templates/hono-typescript/src/app.ts +179 -179
  41. package/src/functions/templates/hono-typescript/src/context.ts +102 -102
  42. package/src/functions/templates/hono-typescript/src/{index.ts → main.ts} +53 -53
  43. package/src/functions/templates/hono-typescript/src/middleware/appwrite.ts +118 -118
  44. package/src/functions/templates/typescript-node/README.md +31 -31
  45. package/src/functions/templates/typescript-node/src/context.ts +102 -102
  46. package/src/functions/templates/typescript-node/src/{index.ts → main.ts} +29 -29
  47. package/src/functions/templates/uv/README.md +30 -30
  48. package/src/functions/templates/uv/pyproject.toml +29 -29
  49. package/src/functions/templates/uv/src/context.py +124 -124
  50. package/src/functions/templates/uv/src/{index.py → main.py} +45 -45
  51. package/src/init.ts +62 -62
  52. package/src/interactiveCLI.ts +1095 -1030
  53. package/src/main.ts +1517 -1670
  54. package/src/migrations/afterImportActions.ts +579 -580
  55. package/src/migrations/appwriteToX.ts +634 -630
  56. package/src/migrations/comprehensiveTransfer.ts +2149 -2149
  57. package/src/migrations/dataLoader.ts +1729 -1702
  58. package/src/migrations/importController.ts +440 -428
  59. package/src/migrations/importDataActions.ts +315 -315
  60. package/src/migrations/relationships.ts +333 -334
  61. package/src/migrations/services/DataTransformationService.ts +195 -195
  62. package/src/migrations/services/FileHandlerService.ts +310 -310
  63. package/src/migrations/services/ImportOrchestrator.ts +674 -665
  64. package/src/migrations/services/RateLimitManager.ts +362 -362
  65. package/src/migrations/services/RelationshipResolver.ts +460 -460
  66. package/src/migrations/services/UserMappingService.ts +344 -344
  67. package/src/migrations/services/ValidationService.ts +333 -333
  68. package/src/migrations/transfer.ts +987 -942
  69. package/src/migrations/yaml/YamlImportConfigLoader.ts +438 -438
  70. package/src/migrations/yaml/YamlImportIntegration.ts +438 -438
  71. package/src/migrations/yaml/generateImportSchemas.ts +1347 -1347
  72. package/src/schemas/authUser.ts +23 -23
  73. package/src/setup.ts +8 -8
  74. package/src/setupCommands.ts +5 -6
  75. package/src/setupController.ts +42 -42
  76. package/src/shared/backupMetadataSchema.ts +93 -93
  77. package/src/shared/backupTracking.ts +211 -211
  78. package/src/shared/confirmationDialogs.ts +326 -326
  79. package/src/shared/migrationHelpers.ts +232 -232
  80. package/src/shared/operationLogger.ts +20 -20
  81. package/src/shared/operationQueue.ts +326 -327
  82. package/src/shared/operationsTable.ts +338 -338
  83. package/src/shared/operationsTableSchema.ts +60 -60
  84. package/src/shared/progressManager.ts +277 -277
  85. package/src/shared/relationshipExtractor.ts +214 -214
  86. package/src/shared/selectionDialogs.ts +775 -722
  87. package/src/storage/backupCompression.ts +88 -88
  88. package/src/storage/methods.ts +695 -682
  89. package/src/storage/schemas.ts +205 -205
  90. package/src/tables/indexManager.ts +408 -408
  91. package/src/types/node-appwrite-tablesdb.d.ts +43 -43
  92. package/src/types.ts +9 -9
  93. package/src/users/methods.ts +358 -359
  94. package/src/utils/configMigration.ts +347 -347
  95. package/src/utils/index.ts +2 -2
  96. package/src/utils/loadConfigs.ts +457 -449
  97. package/src/utils/setupFiles.ts +1236 -1238
  98. package/src/utilsController.ts +1263 -1213
  99. package/tests/README.md +496 -496
  100. package/tests/adapters/AdapterFactory.test.ts +276 -276
  101. package/tests/integration/syncOperations.test.ts +462 -462
  102. package/tests/jest.config.js +24 -24
  103. package/tests/migration/configMigration.test.ts +545 -545
  104. package/tests/setup.ts +61 -61
  105. package/tests/testUtils.ts +339 -339
  106. package/tests/utils/loadConfigs.test.ts +349 -349
  107. package/tests/validation/configValidation.test.ts +411 -411
  108. package/tsconfig.json +44 -44
  109. package/.appwrite/.yaml_schemas/appwrite-config.schema.json +0 -380
  110. package/.appwrite/.yaml_schemas/collection.schema.json +0 -255
  111. package/.appwrite/collections/Categories.yaml +0 -182
  112. package/.appwrite/collections/ExampleCollection.yaml +0 -36
  113. package/.appwrite/collections/Posts.yaml +0 -227
  114. package/.appwrite/collections/Users.yaml +0 -149
  115. package/.appwrite/config.yaml +0 -109
  116. package/.appwrite/import/README.md +0 -148
  117. package/.appwrite/import/categories-import.yaml +0 -129
  118. package/.appwrite/import/posts-import.yaml +0 -208
  119. package/.appwrite/import/users-import.yaml +0 -130
  120. package/.appwrite/importData/categories.json +0 -194
  121. package/.appwrite/importData/posts.json +0 -270
  122. package/.appwrite/importData/users.json +0 -220
  123. package/.appwrite/schemas/categories.json +0 -128
  124. package/.appwrite/schemas/exampleCollection.json +0 -52
  125. package/.appwrite/schemas/posts.json +0 -173
  126. package/.appwrite/schemas/users.json +0 -125
  127. package/dist/adapters/AdapterFactory.d.ts +0 -94
  128. package/dist/adapters/AdapterFactory.js +0 -420
  129. package/dist/adapters/DatabaseAdapter.d.ts +0 -243
  130. package/dist/adapters/DatabaseAdapter.js +0 -50
  131. package/dist/adapters/LegacyAdapter.d.ts +0 -50
  132. package/dist/adapters/LegacyAdapter.js +0 -615
  133. package/dist/adapters/TablesDBAdapter.d.ts +0 -45
  134. package/dist/adapters/TablesDBAdapter.js +0 -611
  135. package/dist/adapters/index.d.ts +0 -11
  136. package/dist/adapters/index.js +0 -12
  137. package/dist/backups/operations/bucketBackup.d.ts +0 -19
  138. package/dist/backups/operations/bucketBackup.js +0 -197
  139. package/dist/backups/operations/collectionBackup.d.ts +0 -30
  140. package/dist/backups/operations/collectionBackup.js +0 -201
  141. package/dist/backups/operations/comprehensiveBackup.d.ts +0 -25
  142. package/dist/backups/operations/comprehensiveBackup.js +0 -238
  143. package/dist/backups/schemas/bucketManifest.d.ts +0 -93
  144. package/dist/backups/schemas/bucketManifest.js +0 -33
  145. package/dist/backups/schemas/comprehensiveManifest.d.ts +0 -108
  146. package/dist/backups/schemas/comprehensiveManifest.js +0 -32
  147. package/dist/backups/tracking/centralizedTracking.d.ts +0 -34
  148. package/dist/backups/tracking/centralizedTracking.js +0 -274
  149. package/dist/cli/commands/configCommands.d.ts +0 -8
  150. package/dist/cli/commands/configCommands.js +0 -166
  151. package/dist/cli/commands/databaseCommands.d.ts +0 -14
  152. package/dist/cli/commands/databaseCommands.js +0 -644
  153. package/dist/cli/commands/functionCommands.d.ts +0 -7
  154. package/dist/cli/commands/functionCommands.js +0 -330
  155. package/dist/cli/commands/schemaCommands.d.ts +0 -7
  156. package/dist/cli/commands/schemaCommands.js +0 -169
  157. package/dist/cli/commands/storageCommands.d.ts +0 -5
  158. package/dist/cli/commands/storageCommands.js +0 -143
  159. package/dist/cli/commands/transferCommands.d.ts +0 -5
  160. package/dist/cli/commands/transferCommands.js +0 -384
  161. package/dist/collections/attributes.d.ts +0 -13
  162. package/dist/collections/attributes.js +0 -1333
  163. package/dist/collections/indexes.d.ts +0 -12
  164. package/dist/collections/indexes.js +0 -217
  165. package/dist/collections/methods.d.ts +0 -19
  166. package/dist/collections/methods.js +0 -587
  167. package/dist/collections/tableOperations.d.ts +0 -86
  168. package/dist/collections/tableOperations.js +0 -447
  169. package/dist/collections/transferOperations.d.ts +0 -8
  170. package/dist/collections/transferOperations.js +0 -412
  171. package/dist/collections/wipeOperations.d.ts +0 -16
  172. package/dist/collections/wipeOperations.js +0 -233
  173. package/dist/config/ConfigManager.d.ts +0 -450
  174. package/dist/config/ConfigManager.js +0 -650
  175. package/dist/config/configMigration.d.ts +0 -87
  176. package/dist/config/configMigration.js +0 -390
  177. package/dist/config/configValidation.d.ts +0 -66
  178. package/dist/config/configValidation.js +0 -358
  179. package/dist/config/index.d.ts +0 -8
  180. package/dist/config/index.js +0 -7
  181. package/dist/config/services/ConfigDiscoveryService.d.ts +0 -122
  182. package/dist/config/services/ConfigDiscoveryService.js +0 -322
  183. package/dist/config/services/ConfigLoaderService.d.ts +0 -129
  184. package/dist/config/services/ConfigLoaderService.js +0 -535
  185. package/dist/config/services/ConfigMergeService.d.ts +0 -208
  186. package/dist/config/services/ConfigMergeService.js +0 -308
  187. package/dist/config/services/ConfigValidationService.d.ts +0 -214
  188. package/dist/config/services/ConfigValidationService.js +0 -310
  189. package/dist/config/services/SessionAuthService.d.ts +0 -225
  190. package/dist/config/services/SessionAuthService.js +0 -456
  191. package/dist/config/services/__tests__/ConfigMergeService.test.d.ts +0 -1
  192. package/dist/config/services/__tests__/ConfigMergeService.test.js +0 -271
  193. package/dist/config/services/index.d.ts +0 -13
  194. package/dist/config/services/index.js +0 -10
  195. package/dist/config/yamlConfig.d.ts +0 -722
  196. package/dist/config/yamlConfig.js +0 -702
  197. package/dist/databases/methods.d.ts +0 -6
  198. package/dist/databases/methods.js +0 -35
  199. package/dist/databases/setup.d.ts +0 -5
  200. package/dist/databases/setup.js +0 -45
  201. package/dist/examples/yamlTerminologyExample.d.ts +0 -42
  202. package/dist/examples/yamlTerminologyExample.js +0 -272
  203. package/dist/functions/deployments.d.ts +0 -4
  204. package/dist/functions/deployments.js +0 -146
  205. package/dist/functions/fnConfigDiscovery.d.ts +0 -3
  206. package/dist/functions/fnConfigDiscovery.js +0 -108
  207. package/dist/functions/methods.d.ts +0 -16
  208. package/dist/functions/methods.js +0 -174
  209. package/dist/functions/pathResolution.d.ts +0 -37
  210. package/dist/functions/pathResolution.js +0 -185
  211. package/dist/functions/templates/count-docs-in-collection/README.md +0 -54
  212. package/dist/functions/templates/count-docs-in-collection/package.json +0 -25
  213. package/dist/functions/templates/count-docs-in-collection/src/main.ts +0 -159
  214. package/dist/functions/templates/count-docs-in-collection/src/request.ts +0 -9
  215. package/dist/functions/templates/count-docs-in-collection/tsconfig.json +0 -28
  216. package/dist/functions/templates/hono-typescript/README.md +0 -286
  217. package/dist/functions/templates/hono-typescript/package.json +0 -26
  218. package/dist/functions/templates/hono-typescript/src/adapters/request.ts +0 -74
  219. package/dist/functions/templates/hono-typescript/src/adapters/response.ts +0 -106
  220. package/dist/functions/templates/hono-typescript/src/app.ts +0 -180
  221. package/dist/functions/templates/hono-typescript/src/context.ts +0 -103
  222. package/dist/functions/templates/hono-typescript/src/index.ts +0 -54
  223. package/dist/functions/templates/hono-typescript/src/middleware/appwrite.ts +0 -119
  224. package/dist/functions/templates/hono-typescript/tsconfig.json +0 -20
  225. package/dist/functions/templates/typescript-node/README.md +0 -32
  226. package/dist/functions/templates/typescript-node/package.json +0 -25
  227. package/dist/functions/templates/typescript-node/src/context.ts +0 -103
  228. package/dist/functions/templates/typescript-node/src/index.ts +0 -29
  229. package/dist/functions/templates/typescript-node/tsconfig.json +0 -28
  230. package/dist/functions/templates/uv/README.md +0 -31
  231. package/dist/functions/templates/uv/pyproject.toml +0 -30
  232. package/dist/functions/templates/uv/src/__init__.py +0 -0
  233. package/dist/functions/templates/uv/src/context.py +0 -125
  234. package/dist/functions/templates/uv/src/index.py +0 -46
  235. package/dist/init.d.ts +0 -2
  236. package/dist/init.js +0 -57
  237. package/dist/interactiveCLI.d.ts +0 -31
  238. package/dist/interactiveCLI.js +0 -898
  239. package/dist/main.d.ts +0 -2
  240. package/dist/main.js +0 -1180
  241. package/dist/migrations/afterImportActions.d.ts +0 -17
  242. package/dist/migrations/afterImportActions.js +0 -306
  243. package/dist/migrations/appwriteToX.d.ts +0 -211
  244. package/dist/migrations/appwriteToX.js +0 -491
  245. package/dist/migrations/comprehensiveTransfer.d.ts +0 -147
  246. package/dist/migrations/comprehensiveTransfer.js +0 -1317
  247. package/dist/migrations/dataLoader.d.ts +0 -753
  248. package/dist/migrations/dataLoader.js +0 -1250
  249. package/dist/migrations/importController.d.ts +0 -23
  250. package/dist/migrations/importController.js +0 -268
  251. package/dist/migrations/importDataActions.d.ts +0 -50
  252. package/dist/migrations/importDataActions.js +0 -230
  253. package/dist/migrations/relationships.d.ts +0 -29
  254. package/dist/migrations/relationships.js +0 -204
  255. package/dist/migrations/services/DataTransformationService.d.ts +0 -55
  256. package/dist/migrations/services/DataTransformationService.js +0 -158
  257. package/dist/migrations/services/FileHandlerService.d.ts +0 -75
  258. package/dist/migrations/services/FileHandlerService.js +0 -236
  259. package/dist/migrations/services/ImportOrchestrator.d.ts +0 -97
  260. package/dist/migrations/services/ImportOrchestrator.js +0 -485
  261. package/dist/migrations/services/RateLimitManager.d.ts +0 -138
  262. package/dist/migrations/services/RateLimitManager.js +0 -279
  263. package/dist/migrations/services/RelationshipResolver.d.ts +0 -120
  264. package/dist/migrations/services/RelationshipResolver.js +0 -332
  265. package/dist/migrations/services/UserMappingService.d.ts +0 -109
  266. package/dist/migrations/services/UserMappingService.js +0 -277
  267. package/dist/migrations/services/ValidationService.d.ts +0 -74
  268. package/dist/migrations/services/ValidationService.js +0 -260
  269. package/dist/migrations/transfer.d.ts +0 -26
  270. package/dist/migrations/transfer.js +0 -608
  271. package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +0 -131
  272. package/dist/migrations/yaml/YamlImportConfigLoader.js +0 -383
  273. package/dist/migrations/yaml/YamlImportIntegration.d.ts +0 -93
  274. package/dist/migrations/yaml/YamlImportIntegration.js +0 -341
  275. package/dist/migrations/yaml/generateImportSchemas.d.ts +0 -30
  276. package/dist/migrations/yaml/generateImportSchemas.js +0 -1327
  277. package/dist/schemas/authUser.d.ts +0 -24
  278. package/dist/schemas/authUser.js +0 -17
  279. package/dist/setup.d.ts +0 -2
  280. package/dist/setup.js +0 -5
  281. package/dist/setupCommands.d.ts +0 -58
  282. package/dist/setupCommands.js +0 -490
  283. package/dist/setupController.d.ts +0 -9
  284. package/dist/setupController.js +0 -34
  285. package/dist/shared/attributeMapper.d.ts +0 -20
  286. package/dist/shared/attributeMapper.js +0 -203
  287. package/dist/shared/backupMetadataSchema.d.ts +0 -94
  288. package/dist/shared/backupMetadataSchema.js +0 -38
  289. package/dist/shared/backupTracking.d.ts +0 -18
  290. package/dist/shared/backupTracking.js +0 -176
  291. package/dist/shared/confirmationDialogs.d.ts +0 -75
  292. package/dist/shared/confirmationDialogs.js +0 -236
  293. package/dist/shared/errorUtils.d.ts +0 -54
  294. package/dist/shared/errorUtils.js +0 -95
  295. package/dist/shared/functionManager.d.ts +0 -48
  296. package/dist/shared/functionManager.js +0 -348
  297. package/dist/shared/jsonSchemaGenerator.d.ts +0 -50
  298. package/dist/shared/jsonSchemaGenerator.js +0 -290
  299. package/dist/shared/logging.d.ts +0 -61
  300. package/dist/shared/logging.js +0 -116
  301. package/dist/shared/messageFormatter.d.ts +0 -39
  302. package/dist/shared/messageFormatter.js +0 -162
  303. package/dist/shared/migrationHelpers.d.ts +0 -61
  304. package/dist/shared/migrationHelpers.js +0 -145
  305. package/dist/shared/operationLogger.d.ts +0 -10
  306. package/dist/shared/operationLogger.js +0 -12
  307. package/dist/shared/operationQueue.d.ts +0 -40
  308. package/dist/shared/operationQueue.js +0 -311
  309. package/dist/shared/operationsTable.d.ts +0 -26
  310. package/dist/shared/operationsTable.js +0 -286
  311. package/dist/shared/operationsTableSchema.d.ts +0 -48
  312. package/dist/shared/operationsTableSchema.js +0 -35
  313. package/dist/shared/progressManager.d.ts +0 -62
  314. package/dist/shared/progressManager.js +0 -215
  315. package/dist/shared/pydanticModelGenerator.d.ts +0 -17
  316. package/dist/shared/pydanticModelGenerator.js +0 -615
  317. package/dist/shared/relationshipExtractor.d.ts +0 -56
  318. package/dist/shared/relationshipExtractor.js +0 -138
  319. package/dist/shared/schemaGenerator.d.ts +0 -40
  320. package/dist/shared/schemaGenerator.js +0 -556
  321. package/dist/shared/selectionDialogs.d.ts +0 -214
  322. package/dist/shared/selectionDialogs.js +0 -544
  323. package/dist/storage/backupCompression.d.ts +0 -20
  324. package/dist/storage/backupCompression.js +0 -67
  325. package/dist/storage/methods.d.ts +0 -32
  326. package/dist/storage/methods.js +0 -472
  327. package/dist/storage/schemas.d.ts +0 -842
  328. package/dist/storage/schemas.js +0 -175
  329. package/dist/tables/indexManager.d.ts +0 -65
  330. package/dist/tables/indexManager.js +0 -294
  331. package/dist/types.d.ts +0 -4
  332. package/dist/types.js +0 -3
  333. package/dist/users/methods.d.ts +0 -16
  334. package/dist/users/methods.js +0 -277
  335. package/dist/utils/ClientFactory.d.ts +0 -87
  336. package/dist/utils/ClientFactory.js +0 -212
  337. package/dist/utils/configDiscovery.d.ts +0 -78
  338. package/dist/utils/configDiscovery.js +0 -472
  339. package/dist/utils/configMigration.d.ts +0 -1
  340. package/dist/utils/configMigration.js +0 -261
  341. package/dist/utils/constantsGenerator.d.ts +0 -31
  342. package/dist/utils/constantsGenerator.js +0 -321
  343. package/dist/utils/dataConverters.d.ts +0 -46
  344. package/dist/utils/dataConverters.js +0 -139
  345. package/dist/utils/directoryUtils.d.ts +0 -22
  346. package/dist/utils/directoryUtils.js +0 -59
  347. package/dist/utils/getClientFromConfig.d.ts +0 -39
  348. package/dist/utils/getClientFromConfig.js +0 -199
  349. package/dist/utils/helperFunctions.d.ts +0 -63
  350. package/dist/utils/helperFunctions.js +0 -156
  351. package/dist/utils/index.d.ts +0 -2
  352. package/dist/utils/index.js +0 -2
  353. package/dist/utils/loadConfigs.d.ts +0 -50
  354. package/dist/utils/loadConfigs.js +0 -358
  355. package/dist/utils/pathResolvers.d.ts +0 -53
  356. package/dist/utils/pathResolvers.js +0 -72
  357. package/dist/utils/projectConfig.d.ts +0 -122
  358. package/dist/utils/projectConfig.js +0 -206
  359. package/dist/utils/retryFailedPromises.d.ts +0 -2
  360. package/dist/utils/retryFailedPromises.js +0 -23
  361. package/dist/utils/sessionAuth.d.ts +0 -48
  362. package/dist/utils/sessionAuth.js +0 -164
  363. package/dist/utils/setupFiles.d.ts +0 -4
  364. package/dist/utils/setupFiles.js +0 -1192
  365. package/dist/utils/typeGuards.d.ts +0 -35
  366. package/dist/utils/typeGuards.js +0 -57
  367. package/dist/utils/validationRules.d.ts +0 -43
  368. package/dist/utils/validationRules.js +0 -42
  369. package/dist/utils/versionDetection.d.ts +0 -58
  370. package/dist/utils/versionDetection.js +0 -251
  371. package/dist/utils/yamlConverter.d.ts +0 -100
  372. package/dist/utils/yamlConverter.js +0 -428
  373. package/dist/utils/yamlLoader.d.ts +0 -70
  374. package/dist/utils/yamlLoader.js +0 -267
  375. package/dist/utilsController.d.ts +0 -107
  376. package/dist/utilsController.js +0 -873
  377. package/src/adapters/AdapterFactory.ts +0 -529
  378. package/src/adapters/DatabaseAdapter.ts +0 -319
  379. package/src/adapters/LegacyAdapter.ts +0 -844
  380. package/src/adapters/TablesDBAdapter.ts +0 -823
  381. package/src/config/ConfigManager.ts +0 -849
  382. package/src/config/README.md +0 -274
  383. package/src/config/configMigration.ts +0 -575
  384. package/src/config/configValidation.ts +0 -445
  385. package/src/config/index.ts +0 -10
  386. package/src/config/services/ConfigDiscoveryService.ts +0 -410
  387. package/src/config/services/ConfigLoaderService.ts +0 -732
  388. package/src/config/services/ConfigMergeService.ts +0 -388
  389. package/src/config/services/ConfigValidationService.ts +0 -394
  390. package/src/config/services/SessionAuthService.ts +0 -565
  391. package/src/config/services/__tests__/ConfigMergeService.test.ts +0 -351
  392. package/src/config/services/index.ts +0 -29
  393. package/src/config/yamlConfig.ts +0 -761
  394. package/src/functions/pathResolution.ts +0 -227
  395. package/src/functions/templates/count-docs-in-collection/package.json +0 -25
  396. package/src/functions/templates/count-docs-in-collection/tsconfig.json +0 -28
  397. package/src/functions/templates/hono-typescript/package.json +0 -26
  398. package/src/functions/templates/hono-typescript/tsconfig.json +0 -20
  399. package/src/functions/templates/typescript-node/package.json +0 -25
  400. package/src/functions/templates/typescript-node/tsconfig.json +0 -28
  401. package/src/shared/attributeMapper.ts +0 -229
  402. package/src/shared/errorUtils.ts +0 -110
  403. package/src/shared/functionManager.ts +0 -537
  404. package/src/shared/jsonSchemaGenerator.ts +0 -383
  405. package/src/shared/logging.ts +0 -149
  406. package/src/shared/messageFormatter.ts +0 -208
  407. package/src/shared/pydanticModelGenerator.ts +0 -618
  408. package/src/shared/schemaGenerator.ts +0 -644
  409. package/src/utils/ClientFactory.ts +0 -240
  410. package/src/utils/configDiscovery.ts +0 -557
  411. package/src/utils/constantsGenerator.ts +0 -369
  412. package/src/utils/dataConverters.ts +0 -159
  413. package/src/utils/directoryUtils.ts +0 -61
  414. package/src/utils/getClientFromConfig.ts +0 -257
  415. package/src/utils/helperFunctions.ts +0 -228
  416. package/src/utils/pathResolvers.ts +0 -81
  417. package/src/utils/projectConfig.ts +0 -340
  418. package/src/utils/retryFailedPromises.ts +0 -29
  419. package/src/utils/sessionAuth.ts +0 -230
  420. package/src/utils/typeGuards.ts +0 -65
  421. package/src/utils/validationRules.ts +0 -88
  422. package/src/utils/versionDetection.ts +0 -292
  423. package/src/utils/yamlConverter.ts +0 -542
  424. package/src/utils/yamlLoader.ts +0 -371
  425. package/tmp-sync-test/.appwrite/collections/TestCollection.yaml +0 -7
@@ -1,449 +1,457 @@
1
- import path from "path";
2
- import fs from "fs";
3
- import { type AppwriteConfig, type Collection, type CollectionCreate, type Table, type TableCreate } from "appwrite-utils";
4
- import { register } from "tsx/esm/api"; // Import the register function
5
- import { pathToFileURL } from "node:url";
6
- import chalk from "chalk";
7
- import { findYamlConfig, loadYamlConfig, loadYamlConfigWithSession, extractSessionOptionsFromConfig, type YamlSessionOptions } from "../config/yamlConfig.js";
8
- import { detectAppwriteVersionCached, fetchServerVersion, isVersionAtLeast } from "./versionDetection.js";
9
- import { MessageFormatter } from "../shared/messageFormatter.js";
10
- import { validateCollectionsTablesConfig, reportValidationResults, type ValidationResult } from "../config/configValidation.js";
11
- import { resolveCollectionsDir, resolveTablesDir } from "./pathResolvers.js";
12
- import {
13
- findAppwriteConfig,
14
- findAppwriteConfigTS,
15
- findFunctionsDir,
16
- discoverCollections,
17
- discoverTables,
18
- discoverLegacyDirectory
19
- } from "./configDiscovery.js";
20
-
21
- /**
22
- * Session authentication preservation options for config loading
23
- */
24
- export interface SessionPreservationOptions {
25
- sessionCookie?: string;
26
- authMethod?: "session" | "apikey" | "auto";
27
- sessionMetadata?: {
28
- email?: string;
29
- expiresAt?: string;
30
- };
31
- }
32
-
33
- /**
34
- * Configuration loading options
35
- */
36
- export interface ConfigLoadingOptions {
37
- validate?: boolean;
38
- strictMode?: boolean;
39
- reportValidation?: boolean;
40
- preserveAuth?: SessionPreservationOptions;
41
- }
42
-
43
- /**
44
- * Helper function to create session preservation options from session data
45
- * @param sessionCookie The session cookie string
46
- * @param email Optional email associated with the session
47
- * @param expiresAt Optional expiration timestamp
48
- * @returns SessionPreservationOptions object
49
- */
50
- export function createSessionPreservation(
51
- sessionCookie: string,
52
- email?: string,
53
- expiresAt?: string
54
- ): SessionPreservationOptions {
55
- return {
56
- sessionCookie,
57
- authMethod: "session",
58
- sessionMetadata: {
59
- ...(email && { email }),
60
- ...(expiresAt && { expiresAt })
61
- }
62
- };
63
- }
64
-
65
- // Re-export config discovery functions for backward compatibility
66
- export { findAppwriteConfig, findFunctionsDir } from "./configDiscovery.js";
67
-
68
- /**
69
- * Loads the Appwrite configuration and returns both config and the path where it was found.
70
- * @param configDir The directory to search for config files.
71
- * @param options Loading options including validation settings and session preservation.
72
- * @returns Object containing the config, path, and validation results.
73
- */
74
- export const loadConfigWithPath = async (
75
- configDir: string,
76
- options: ConfigLoadingOptions = {}
77
- ): Promise<{
78
- config: AppwriteConfig;
79
- actualConfigPath: string;
80
- validation?: ValidationResult;
81
- }> => {
82
- const { validate = true, strictMode = false, reportValidation = true } = options;
83
- let config: AppwriteConfig | null = null;
84
- let actualConfigPath: string | null = null;
85
-
86
- // Convert session preservation options to YAML format
87
- const yamlSessionOptions: YamlSessionOptions | undefined = options.preserveAuth ? {
88
- sessionCookie: options.preserveAuth.sessionCookie,
89
- authMethod: options.preserveAuth.authMethod,
90
- sessionMetadata: options.preserveAuth.sessionMetadata,
91
- } : undefined;
92
-
93
- // Check if we're given the .appwrite directory directly
94
- if (configDir.endsWith('.appwrite')) {
95
- // Look for config files directly in this directory
96
- const possibleYamlFiles = ['config.yaml', 'config.yml', 'appwriteConfig.yaml', 'appwriteConfig.yml'];
97
- for (const fileName of possibleYamlFiles) {
98
- const yamlPath = path.join(configDir, fileName);
99
- if (fs.existsSync(yamlPath)) {
100
- config = yamlSessionOptions
101
- ? await loadYamlConfigWithSession(yamlPath, yamlSessionOptions)
102
- : await loadYamlConfig(yamlPath);
103
- actualConfigPath = yamlPath;
104
- break;
105
- }
106
- }
107
- } else {
108
- // Original logic: search for .appwrite directories
109
- const yamlConfigPath = findYamlConfig(configDir);
110
- if (yamlConfigPath) {
111
- config = yamlSessionOptions
112
- ? await loadYamlConfigWithSession(yamlConfigPath, yamlSessionOptions)
113
- : await loadYamlConfig(yamlConfigPath);
114
- actualConfigPath = yamlConfigPath;
115
- }
116
- }
117
-
118
- // Fall back to TypeScript config if YAML not found or failed to load
119
- if (!config) {
120
- const configPath = path.join(configDir, "appwriteConfig.ts");
121
-
122
- // Only try to load TypeScript config if the file exists
123
- if (fs.existsSync(configPath)) {
124
- const unregister = register(); // Register tsx enhancement
125
-
126
- try {
127
- const configUrl = pathToFileURL(configPath).href;
128
- const configModule = (await import(configUrl));
129
- config = configModule.default?.default || configModule.default || configModule;
130
- if (!config) {
131
- throw new Error("Failed to load config");
132
- }
133
- actualConfigPath = configPath;
134
- } finally {
135
- unregister(); // Unregister tsx when done
136
- }
137
- }
138
- }
139
-
140
- if (!config || !actualConfigPath) {
141
- throw new Error("No valid configuration found");
142
- }
143
-
144
- // Preserve session authentication if provided
145
- // This allows maintaining session context when config is reloaded during CLI operations
146
- if (options.preserveAuth) {
147
- const { sessionCookie, authMethod, sessionMetadata } = options.preserveAuth;
148
-
149
- // Inject session cookie into the loaded config
150
- if (sessionCookie) {
151
- config.sessionCookie = sessionCookie;
152
- }
153
-
154
- // Set or override authentication method preference
155
- if (authMethod) {
156
- config.authMethod = authMethod;
157
- }
158
-
159
- // Merge session metadata (email, expiration, etc.) with existing metadata
160
- if (sessionMetadata) {
161
- config.sessionMetadata = {
162
- ...config.sessionMetadata,
163
- ...sessionMetadata
164
- };
165
- }
166
-
167
- // Auto-detect authentication method if not explicitly provided
168
- // If we have a session cookie but no auth method specified, prefer session auth
169
- if (!authMethod && sessionCookie) {
170
- config.authMethod = "session";
171
- }
172
- }
173
-
174
- // Enhanced dual folder support: Load from BOTH collections/ AND tables/ directories
175
- const configFileDir = path.dirname(actualConfigPath);
176
- // Look for collections/tables directories in the same directory as the config file
177
- const collectionsDir = resolveCollectionsDir(configFileDir);
178
- const tablesDir = resolveTablesDir(configFileDir);
179
-
180
- // Initialize collections array
181
- config.collections = [];
182
-
183
- // Load from collections/ directory first (higher priority)
184
- const collectionsResult = await discoverCollections(collectionsDir);
185
- config.collections.push(...collectionsResult.collections);
186
-
187
- // Load from tables/ directory second (lower priority, check for conflicts)
188
- const tablesResult = await discoverTables(tablesDir, collectionsResult.loadedNames);
189
- config.collections.push(...tablesResult.tables);
190
-
191
- // Combine conflicts from both discovery operations
192
- const allConflicts = [...collectionsResult.conflicts, ...tablesResult.conflicts];
193
-
194
- // Report conflicts if any
195
- if (allConflicts.length > 0) {
196
- MessageFormatter.warning(`Found ${allConflicts.length} naming conflicts between collections/ and tables/`, { prefix: "Config" });
197
- allConflicts.forEach(conflict => {
198
- MessageFormatter.info(` - '${conflict.name}': ${conflict.source1} (used) vs ${conflict.source2} (skipped)`, { prefix: "Config" });
199
- });
200
- }
201
-
202
- // Fallback: If neither directory exists, try legacy single-directory detection
203
- if (!fs.existsSync(collectionsDir) && !fs.existsSync(tablesDir)) {
204
- // Determine directory (collections or tables) based on server version / API mode
205
- let dirName: 'collections' | 'tables' = "collections";
206
- try {
207
- const det = await detectAppwriteVersionCached(config.appwriteEndpoint, config.appwriteProject, config.appwriteKey);
208
- if (det.apiMode === 'tablesdb' || isVersionAtLeast(det.serverVersion, '1.8.0')) {
209
- dirName = 'tables';
210
- } else {
211
- // Try health version if not provided
212
- const ver = await fetchServerVersion(config.appwriteEndpoint);
213
- if (isVersionAtLeast(ver || undefined, '1.8.0')) dirName = 'tables';
214
- }
215
- } catch {}
216
-
217
- const legacyItems = await discoverLegacyDirectory(configFileDir, dirName);
218
- config.collections.push(...legacyItems);
219
- }
220
-
221
- // Ensure array exists even if empty
222
- config.collections = config.collections || [];
223
-
224
- // Log the final result
225
- const allCollections = config.collections || [];
226
- const fromCollectionsDir = allCollections.filter((c: any) => !c._isFromTablesDir).length;
227
- const fromTablesDir = allCollections.filter((c: any) => c._isFromTablesDir).length;
228
- const totalLoaded = allCollections.length;
229
-
230
- if (totalLoaded > 0) {
231
- if (fromTablesDir > 0) {
232
- MessageFormatter.success(`Successfully loaded ${totalLoaded} items total: ${fromCollectionsDir} from collections/ and ${fromTablesDir} from tables/`, { prefix: "Config" });
233
- } else {
234
- MessageFormatter.success(`Successfully loaded ${totalLoaded} collections from collections/`, { prefix: "Config" });
235
- }
236
- }
237
-
238
- // Validate configuration if requested
239
- let validation: ValidationResult | undefined;
240
- if (validate) {
241
- validation = validateCollectionsTablesConfig(config);
242
-
243
- // In strict mode, treat warnings as errors
244
- if (strictMode && validation.warnings.length > 0) {
245
- const strictValidation = {
246
- ...validation,
247
- isValid: false,
248
- errors: [...validation.errors, ...validation.warnings.map(w => ({ ...w, severity: "error" as const }))],
249
- warnings: []
250
- };
251
- validation = strictValidation;
252
- }
253
-
254
- // Report validation results if requested
255
- if (reportValidation) {
256
- reportValidationResults(validation, { verbose: true });
257
- }
258
-
259
- // Throw error if validation fails in strict mode
260
- if (strictMode && !validation.isValid) {
261
- throw new Error(`Configuration validation failed in strict mode. Found ${validation.errors.length} validation errors.`);
262
- }
263
- }
264
-
265
- return { config, actualConfigPath, validation };
266
- };
267
-
268
- /**
269
- * Loads the Appwrite configuration and all collection configurations from a specified directory.
270
- * Supports both YAML and TypeScript config formats with backward compatibility.
271
- * @param configDir The directory containing the config file and collections folder.
272
- * @param options Loading options including validation settings and session preservation.
273
- * @returns The loaded Appwrite configuration including collections.
274
- */
275
- export const loadConfig = async (
276
- configDir: string,
277
- options: ConfigLoadingOptions = {}
278
- ): Promise<AppwriteConfig> => {
279
- const { validate = false, strictMode = false, reportValidation = false } = options;
280
- let config: AppwriteConfig | null = null;
281
- let actualConfigPath: string | null = null;
282
-
283
- // Convert session preservation options to YAML format
284
- const yamlSessionOptions: YamlSessionOptions | undefined = options.preserveAuth ? {
285
- sessionCookie: options.preserveAuth.sessionCookie,
286
- authMethod: options.preserveAuth.authMethod,
287
- sessionMetadata: options.preserveAuth.sessionMetadata,
288
- } : undefined;
289
-
290
- // First try to find and load YAML config
291
- const yamlConfigPath = findYamlConfig(configDir);
292
- if (yamlConfigPath) {
293
- config = yamlSessionOptions
294
- ? await loadYamlConfigWithSession(yamlConfigPath, yamlSessionOptions)
295
- : await loadYamlConfig(yamlConfigPath);
296
- actualConfigPath = yamlConfigPath;
297
- }
298
-
299
- // Fall back to TypeScript config if YAML not found or failed to load
300
- if (!config) {
301
- const configPath = path.join(configDir, "appwriteConfig.ts");
302
-
303
- // Only try to load TypeScript config if the file exists
304
- if (fs.existsSync(configPath)) {
305
- const unregister = register(); // Register tsx enhancement
306
-
307
- try {
308
- const configUrl = pathToFileURL(configPath).href;
309
- const configModule = (await import(configUrl));
310
- config = configModule.default?.default || configModule.default || configModule;
311
- if (!config) {
312
- throw new Error("Failed to load config");
313
- }
314
- actualConfigPath = configPath;
315
- } finally {
316
- unregister(); // Unregister tsx when done
317
- }
318
- }
319
- }
320
-
321
- if (!config) {
322
- throw new Error("No valid configuration found");
323
- }
324
-
325
- // Preserve session authentication if provided
326
- // This allows maintaining session context when config is reloaded during CLI operations
327
- if (options.preserveAuth) {
328
- const { sessionCookie, authMethod, sessionMetadata } = options.preserveAuth;
329
-
330
- // Inject session cookie into the loaded config
331
- if (sessionCookie) {
332
- config.sessionCookie = sessionCookie;
333
- }
334
-
335
- // Set or override authentication method preference
336
- if (authMethod) {
337
- config.authMethod = authMethod;
338
- }
339
-
340
- // Merge session metadata (email, expiration, etc.) with existing metadata
341
- if (sessionMetadata) {
342
- config.sessionMetadata = {
343
- ...config.sessionMetadata,
344
- ...sessionMetadata
345
- };
346
- }
347
-
348
- // Auto-detect authentication method if not explicitly provided
349
- // If we have a session cookie but no auth method specified, prefer session auth
350
- if (!authMethod && sessionCookie) {
351
- config.authMethod = "session";
352
- }
353
- }
354
-
355
- // Enhanced dual folder support: Load from BOTH collections/ AND tables/ directories
356
- const configFileDir = actualConfigPath ? path.dirname(actualConfigPath) : configDir;
357
- // Look for collections/tables directories in the same directory as the config file
358
- const collectionsDir = resolveCollectionsDir(configFileDir);
359
- const tablesDir = resolveTablesDir(configFileDir);
360
-
361
- // Initialize collections array
362
- config.collections = [];
363
-
364
- // Load from collections/ directory first (higher priority)
365
- const collectionsResult = await discoverCollections(collectionsDir);
366
- config.collections.push(...collectionsResult.collections);
367
-
368
- // Load from tables/ directory second (lower priority, check for conflicts)
369
- const tablesResult = await discoverTables(tablesDir, collectionsResult.loadedNames);
370
- config.collections.push(...tablesResult.tables);
371
-
372
- // Combine conflicts from both discovery operations
373
- const allConflicts = [...collectionsResult.conflicts, ...tablesResult.conflicts];
374
-
375
- // Report conflicts if any
376
- if (allConflicts.length > 0) {
377
- MessageFormatter.warning(`Found ${allConflicts.length} naming conflicts between collections/ and tables/`, { prefix: "Config" });
378
- allConflicts.forEach(conflict => {
379
- MessageFormatter.info(` - '${conflict.name}': ${conflict.source1} (used) vs ${conflict.source2} (skipped)`, { prefix: "Config" });
380
- });
381
- }
382
-
383
- // Fallback: If neither directory exists, try legacy single-directory detection
384
- if (!fs.existsSync(collectionsDir) && !fs.existsSync(tablesDir)) {
385
- // Determine directory (collections or tables) based on server version / API mode
386
- let dirName: 'collections' | 'tables' = "collections";
387
- try {
388
- const det = await detectAppwriteVersionCached(config.appwriteEndpoint, config.appwriteProject, config.appwriteKey);
389
- if (det.apiMode === 'tablesdb' || isVersionAtLeast(det.serverVersion, '1.8.0')) {
390
- dirName = 'tables';
391
- } else {
392
- const ver = await fetchServerVersion(config.appwriteEndpoint);
393
- if (isVersionAtLeast(ver || undefined, '1.8.0')) dirName = 'tables';
394
- }
395
- } catch {}
396
-
397
- const legacyItems = await discoverLegacyDirectory(configFileDir, dirName);
398
- config.collections.push(...legacyItems);
399
- }
400
-
401
- // Ensure array exists even if empty
402
- config.collections = config.collections || [];
403
-
404
- // Log the final result
405
- const allCollections = config.collections || [];
406
- const fromCollectionsDir = allCollections.filter((c: any) => !c._isFromTablesDir).length;
407
- const fromTablesDir = allCollections.filter((c: any) => c._isFromTablesDir).length;
408
- const totalLoaded = allCollections.length;
409
-
410
- if (totalLoaded > 0) {
411
- if (fromTablesDir > 0) {
412
- MessageFormatter.success(`Successfully loaded ${totalLoaded} items total: ${fromCollectionsDir} from collections/ and ${fromTablesDir} from tables/`, { prefix: "Config" });
413
- } else {
414
- MessageFormatter.success(`Successfully loaded ${totalLoaded} collections from collections/`, { prefix: "Config" });
415
- }
416
- }
417
-
418
- // Log successful config loading
419
- if (actualConfigPath) {
420
- MessageFormatter.success(`Loaded config from: ${actualConfigPath}`, { prefix: "Config" });
421
- }
422
-
423
- // Validate configuration if requested
424
- if (validate) {
425
- let validation = validateCollectionsTablesConfig(config);
426
-
427
- // In strict mode, treat warnings as errors
428
- if (strictMode && validation.warnings.length > 0) {
429
- validation = {
430
- ...validation,
431
- isValid: false,
432
- errors: [...validation.errors, ...validation.warnings.map(w => ({ ...w, severity: "error" as const }))],
433
- warnings: []
434
- };
435
- }
436
-
437
- // Report validation results if requested
438
- if (reportValidation) {
439
- reportValidationResults(validation, { verbose: true });
440
- }
441
-
442
- // Throw error if validation fails in strict mode
443
- if (strictMode && !validation.isValid) {
444
- throw new Error(`Configuration validation failed in strict mode. Found ${validation.errors.length} validation errors.`);
445
- }
446
- }
447
-
448
- return config;
449
- };
1
+ import path from "path";
2
+ import fs from "fs";
3
+ import { type AppwriteConfig, type Collection, type CollectionCreate, type Table, type TableCreate } from "appwrite-utils";
4
+ import { register } from "tsx/esm/api"; // Import the register function
5
+ import { pathToFileURL } from "node:url";
6
+ import chalk from "chalk";
7
+ import {
8
+ findYamlConfig,
9
+ loadYamlConfig,
10
+ loadYamlConfigWithSession,
11
+ extractSessionOptionsFromConfig,
12
+ validateCollectionsTablesConfig,
13
+ reportValidationResults,
14
+ type YamlSessionOptions,
15
+ type ValidationResult
16
+ } from "appwrite-utils-helpers";
17
+ import { detectAppwriteVersionCached, fetchServerVersion, isVersionAtLeast } from 'appwrite-utils-helpers';
18
+ import { MessageFormatter } from "appwrite-utils-helpers";
19
+ import { resolveCollectionsDir, resolveTablesDir } from 'appwrite-utils-helpers';
20
+ import {
21
+ findAppwriteConfig,
22
+ findAppwriteConfigTS,
23
+ findFunctionsDir,
24
+ discoverCollections,
25
+ discoverTables,
26
+ discoverLegacyDirectory
27
+ } from 'appwrite-utils-helpers';
28
+
29
+ /**
30
+ * Session authentication preservation options for config loading
31
+ */
32
+ export interface SessionPreservationOptions {
33
+ sessionCookie?: string;
34
+ authMethod?: "session" | "apikey" | "auto";
35
+ sessionMetadata?: {
36
+ email?: string;
37
+ expiresAt?: string;
38
+ };
39
+ }
40
+
41
+ /**
42
+ * Configuration loading options
43
+ */
44
+ export interface ConfigLoadingOptions {
45
+ validate?: boolean;
46
+ strictMode?: boolean;
47
+ reportValidation?: boolean;
48
+ preserveAuth?: SessionPreservationOptions;
49
+ }
50
+
51
+ /**
52
+ * Helper function to create session preservation options from session data
53
+ * @param sessionCookie The session cookie string
54
+ * @param email Optional email associated with the session
55
+ * @param expiresAt Optional expiration timestamp
56
+ * @returns SessionPreservationOptions object
57
+ */
58
+ export function createSessionPreservation(
59
+ sessionCookie: string,
60
+ email?: string,
61
+ expiresAt?: string
62
+ ): SessionPreservationOptions {
63
+ return {
64
+ sessionCookie,
65
+ authMethod: "session",
66
+ sessionMetadata: {
67
+ ...(email && { email }),
68
+ ...(expiresAt && { expiresAt })
69
+ }
70
+ };
71
+ }
72
+
73
+ // Re-export config discovery functions for backward compatibility
74
+ export { findAppwriteConfig, findFunctionsDir } from 'appwrite-utils-helpers';
75
+
76
+ /**
77
+ * Loads the Appwrite configuration and returns both config and the path where it was found.
78
+ * @param configDir The directory to search for config files.
79
+ * @param options Loading options including validation settings and session preservation.
80
+ * @returns Object containing the config, path, and validation results.
81
+ */
82
+ export const loadConfigWithPath = async (
83
+ configDir: string,
84
+ options: ConfigLoadingOptions = {}
85
+ ): Promise<{
86
+ config: AppwriteConfig;
87
+ actualConfigPath: string;
88
+ validation?: ValidationResult;
89
+ }> => {
90
+ const { validate = true, strictMode = false, reportValidation = true } = options;
91
+ let config: AppwriteConfig | null = null;
92
+ let actualConfigPath: string | null = null;
93
+
94
+ // Convert session preservation options to YAML format
95
+ const yamlSessionOptions: YamlSessionOptions | undefined = options.preserveAuth ? {
96
+ sessionCookie: options.preserveAuth.sessionCookie,
97
+ authMethod: options.preserveAuth.authMethod,
98
+ sessionMetadata: options.preserveAuth.sessionMetadata,
99
+ } : undefined;
100
+
101
+ // Check if we're given the .appwrite directory directly
102
+ if (configDir.endsWith('.appwrite')) {
103
+ // Look for config files directly in this directory
104
+ const possibleYamlFiles = ['config.yaml', 'config.yml', 'appwriteConfig.yaml', 'appwriteConfig.yml'];
105
+ for (const fileName of possibleYamlFiles) {
106
+ const yamlPath = path.join(configDir, fileName);
107
+ if (fs.existsSync(yamlPath)) {
108
+ config = yamlSessionOptions
109
+ ? await loadYamlConfigWithSession(yamlPath, yamlSessionOptions)
110
+ : await loadYamlConfig(yamlPath);
111
+ actualConfigPath = yamlPath;
112
+ break;
113
+ }
114
+ }
115
+ } else {
116
+ // Original logic: search for .appwrite directories
117
+ const yamlConfigPath = findYamlConfig(configDir);
118
+ if (yamlConfigPath) {
119
+ config = yamlSessionOptions
120
+ ? await loadYamlConfigWithSession(yamlConfigPath, yamlSessionOptions)
121
+ : await loadYamlConfig(yamlConfigPath);
122
+ actualConfigPath = yamlConfigPath;
123
+ }
124
+ }
125
+
126
+ // Fall back to TypeScript config if YAML not found or failed to load
127
+ if (!config) {
128
+ const configPath = path.join(configDir, "appwriteConfig.ts");
129
+
130
+ // Only try to load TypeScript config if the file exists
131
+ if (fs.existsSync(configPath)) {
132
+ const unregister = register(); // Register tsx enhancement
133
+
134
+ try {
135
+ const configUrl = pathToFileURL(configPath).href;
136
+ const configModule = (await import(configUrl));
137
+ config = configModule.default?.default || configModule.default || configModule;
138
+ if (!config) {
139
+ throw new Error("Failed to load config");
140
+ }
141
+ actualConfigPath = configPath;
142
+ } finally {
143
+ unregister(); // Unregister tsx when done
144
+ }
145
+ }
146
+ }
147
+
148
+ if (!config || !actualConfigPath) {
149
+ throw new Error("No valid configuration found");
150
+ }
151
+
152
+ // Preserve session authentication if provided
153
+ // This allows maintaining session context when config is reloaded during CLI operations
154
+ if (options.preserveAuth) {
155
+ const { sessionCookie, authMethod, sessionMetadata } = options.preserveAuth;
156
+
157
+ // Inject session cookie into the loaded config
158
+ if (sessionCookie) {
159
+ config.sessionCookie = sessionCookie;
160
+ }
161
+
162
+ // Set or override authentication method preference
163
+ if (authMethod) {
164
+ config.authMethod = authMethod;
165
+ }
166
+
167
+ // Merge session metadata (email, expiration, etc.) with existing metadata
168
+ if (sessionMetadata) {
169
+ config.sessionMetadata = {
170
+ ...config.sessionMetadata,
171
+ ...sessionMetadata
172
+ };
173
+ }
174
+
175
+ // Auto-detect authentication method if not explicitly provided
176
+ // If we have a session cookie but no auth method specified, prefer session auth
177
+ if (!authMethod && sessionCookie) {
178
+ config.authMethod = "session";
179
+ }
180
+ }
181
+
182
+ // Enhanced dual folder support: Load from BOTH collections/ AND tables/ directories
183
+ const configFileDir = path.dirname(actualConfigPath);
184
+ // Look for collections/tables directories in the same directory as the config file
185
+ const collectionsDir = resolveCollectionsDir(configFileDir);
186
+ const tablesDir = resolveTablesDir(configFileDir);
187
+
188
+ // Initialize collections array
189
+ config.collections = [];
190
+
191
+ // Load from collections/ directory first (higher priority)
192
+ const collectionsResult = await discoverCollections(collectionsDir);
193
+ config.collections.push(...collectionsResult.collections);
194
+
195
+ // Load from tables/ directory second (lower priority, check for conflicts)
196
+ const tablesResult = await discoverTables(tablesDir, collectionsResult.loadedNames);
197
+ config.collections.push(...tablesResult.tables);
198
+
199
+ // Combine conflicts from both discovery operations
200
+ const allConflicts = [...collectionsResult.conflicts, ...tablesResult.conflicts];
201
+
202
+ // Report conflicts if any
203
+ if (allConflicts.length > 0) {
204
+ MessageFormatter.warning(`Found ${allConflicts.length} naming conflicts between collections/ and tables/`, { prefix: "Config" });
205
+ allConflicts.forEach(conflict => {
206
+ MessageFormatter.info(` - '${conflict.name}': ${conflict.source1} (used) vs ${conflict.source2} (skipped)`, { prefix: "Config" });
207
+ });
208
+ }
209
+
210
+ // Fallback: If neither directory exists, try legacy single-directory detection
211
+ if (!fs.existsSync(collectionsDir) && !fs.existsSync(tablesDir)) {
212
+ // Determine directory (collections or tables) based on server version / API mode
213
+ let dirName: 'collections' | 'tables' = "collections";
214
+ try {
215
+ const det = await detectAppwriteVersionCached(config.appwriteEndpoint, config.appwriteProject, config.appwriteKey);
216
+ if (det.apiMode === 'tablesdb' || isVersionAtLeast(det.serverVersion, '1.8.0')) {
217
+ dirName = 'tables';
218
+ } else {
219
+ // Try health version if not provided
220
+ const ver = await fetchServerVersion(config.appwriteEndpoint);
221
+ if (isVersionAtLeast(ver || undefined, '1.8.0')) dirName = 'tables';
222
+ }
223
+ } catch {}
224
+
225
+ const legacyItems = await discoverLegacyDirectory(configFileDir, dirName);
226
+ config.collections.push(...legacyItems);
227
+ }
228
+
229
+ // Ensure array exists even if empty
230
+ config.collections = config.collections || [];
231
+
232
+ // Log the final result
233
+ const allCollections = config.collections || [];
234
+ const fromCollectionsDir = allCollections.filter((c: any) => !c._isFromTablesDir).length;
235
+ const fromTablesDir = allCollections.filter((c: any) => c._isFromTablesDir).length;
236
+ const totalLoaded = allCollections.length;
237
+
238
+ if (totalLoaded > 0) {
239
+ if (fromTablesDir > 0) {
240
+ MessageFormatter.success(`Successfully loaded ${totalLoaded} items total: ${fromCollectionsDir} from collections/ and ${fromTablesDir} from tables/`, { prefix: "Config" });
241
+ } else {
242
+ MessageFormatter.success(`Successfully loaded ${totalLoaded} collections from collections/`, { prefix: "Config" });
243
+ }
244
+ }
245
+
246
+ // Validate configuration if requested
247
+ let validation: ValidationResult | undefined;
248
+ if (validate) {
249
+ validation = validateCollectionsTablesConfig(config);
250
+
251
+ // In strict mode, treat warnings as errors
252
+ if (strictMode && validation.warnings.length > 0) {
253
+ const strictValidation = {
254
+ ...validation,
255
+ isValid: false,
256
+ errors: [...validation.errors, ...validation.warnings.map(w => ({ ...w, severity: "error" as const }))],
257
+ warnings: []
258
+ };
259
+ validation = strictValidation;
260
+ }
261
+
262
+ // Report validation results if requested
263
+ if (reportValidation) {
264
+ reportValidationResults(validation, { verbose: true });
265
+ }
266
+
267
+ // Throw error if validation fails in strict mode
268
+ if (strictMode && !validation.isValid) {
269
+ throw new Error(`Configuration validation failed in strict mode. Found ${validation.errors.length} validation errors.`);
270
+ }
271
+ }
272
+
273
+ return { config, actualConfigPath, validation };
274
+ };
275
+
276
+ /**
277
+ * Loads the Appwrite configuration and all collection configurations from a specified directory.
278
+ * Supports both YAML and TypeScript config formats with backward compatibility.
279
+ * @param configDir The directory containing the config file and collections folder.
280
+ * @param options Loading options including validation settings and session preservation.
281
+ * @returns The loaded Appwrite configuration including collections.
282
+ */
283
+ export const loadConfig = async (
284
+ configDir: string,
285
+ options: ConfigLoadingOptions = {}
286
+ ): Promise<AppwriteConfig> => {
287
+ const { validate = false, strictMode = false, reportValidation = false } = options;
288
+ let config: AppwriteConfig | null = null;
289
+ let actualConfigPath: string | null = null;
290
+
291
+ // Convert session preservation options to YAML format
292
+ const yamlSessionOptions: YamlSessionOptions | undefined = options.preserveAuth ? {
293
+ sessionCookie: options.preserveAuth.sessionCookie,
294
+ authMethod: options.preserveAuth.authMethod,
295
+ sessionMetadata: options.preserveAuth.sessionMetadata,
296
+ } : undefined;
297
+
298
+ // First try to find and load YAML config
299
+ const yamlConfigPath = findYamlConfig(configDir);
300
+ if (yamlConfigPath) {
301
+ config = yamlSessionOptions
302
+ ? await loadYamlConfigWithSession(yamlConfigPath, yamlSessionOptions)
303
+ : await loadYamlConfig(yamlConfigPath);
304
+ actualConfigPath = yamlConfigPath;
305
+ }
306
+
307
+ // Fall back to TypeScript config if YAML not found or failed to load
308
+ if (!config) {
309
+ const configPath = path.join(configDir, "appwriteConfig.ts");
310
+
311
+ // Only try to load TypeScript config if the file exists
312
+ if (fs.existsSync(configPath)) {
313
+ const unregister = register(); // Register tsx enhancement
314
+
315
+ try {
316
+ const configUrl = pathToFileURL(configPath).href;
317
+ const configModule = (await import(configUrl));
318
+ config = configModule.default?.default || configModule.default || configModule;
319
+ if (!config) {
320
+ throw new Error("Failed to load config");
321
+ }
322
+ actualConfigPath = configPath;
323
+ } finally {
324
+ unregister(); // Unregister tsx when done
325
+ }
326
+ }
327
+ }
328
+
329
+ if (!config) {
330
+ throw new Error("No valid configuration found");
331
+ }
332
+
333
+ // Preserve session authentication if provided
334
+ // This allows maintaining session context when config is reloaded during CLI operations
335
+ if (options.preserveAuth) {
336
+ const { sessionCookie, authMethod, sessionMetadata } = options.preserveAuth;
337
+
338
+ // Inject session cookie into the loaded config
339
+ if (sessionCookie) {
340
+ config.sessionCookie = sessionCookie;
341
+ }
342
+
343
+ // Set or override authentication method preference
344
+ if (authMethod) {
345
+ config.authMethod = authMethod;
346
+ }
347
+
348
+ // Merge session metadata (email, expiration, etc.) with existing metadata
349
+ if (sessionMetadata) {
350
+ config.sessionMetadata = {
351
+ ...config.sessionMetadata,
352
+ ...sessionMetadata
353
+ };
354
+ }
355
+
356
+ // Auto-detect authentication method if not explicitly provided
357
+ // If we have a session cookie but no auth method specified, prefer session auth
358
+ if (!authMethod && sessionCookie) {
359
+ config.authMethod = "session";
360
+ }
361
+ }
362
+
363
+ // Enhanced dual folder support: Load from BOTH collections/ AND tables/ directories
364
+ const configFileDir = actualConfigPath ? path.dirname(actualConfigPath) : configDir;
365
+ // Look for collections/tables directories in the same directory as the config file
366
+ const collectionsDir = resolveCollectionsDir(configFileDir);
367
+ const tablesDir = resolveTablesDir(configFileDir);
368
+
369
+ // Initialize collections array
370
+ config.collections = [];
371
+
372
+ // Load from collections/ directory first (higher priority)
373
+ const collectionsResult = await discoverCollections(collectionsDir);
374
+ config.collections.push(...collectionsResult.collections);
375
+
376
+ // Load from tables/ directory second (lower priority, check for conflicts)
377
+ const tablesResult = await discoverTables(tablesDir, collectionsResult.loadedNames);
378
+ config.collections.push(...tablesResult.tables);
379
+
380
+ // Combine conflicts from both discovery operations
381
+ const allConflicts = [...collectionsResult.conflicts, ...tablesResult.conflicts];
382
+
383
+ // Report conflicts if any
384
+ if (allConflicts.length > 0) {
385
+ MessageFormatter.warning(`Found ${allConflicts.length} naming conflicts between collections/ and tables/`, { prefix: "Config" });
386
+ allConflicts.forEach(conflict => {
387
+ MessageFormatter.info(` - '${conflict.name}': ${conflict.source1} (used) vs ${conflict.source2} (skipped)`, { prefix: "Config" });
388
+ });
389
+ }
390
+
391
+ // Fallback: If neither directory exists, try legacy single-directory detection
392
+ if (!fs.existsSync(collectionsDir) && !fs.existsSync(tablesDir)) {
393
+ // Determine directory (collections or tables) based on server version / API mode
394
+ let dirName: 'collections' | 'tables' = "collections";
395
+ try {
396
+ const det = await detectAppwriteVersionCached(config.appwriteEndpoint, config.appwriteProject, config.appwriteKey);
397
+ if (det.apiMode === 'tablesdb' || isVersionAtLeast(det.serverVersion, '1.8.0')) {
398
+ dirName = 'tables';
399
+ } else {
400
+ const ver = await fetchServerVersion(config.appwriteEndpoint);
401
+ if (isVersionAtLeast(ver || undefined, '1.8.0')) dirName = 'tables';
402
+ }
403
+ } catch {}
404
+
405
+ const legacyItems = await discoverLegacyDirectory(configFileDir, dirName);
406
+ config.collections.push(...legacyItems);
407
+ }
408
+
409
+ // Ensure array exists even if empty
410
+ config.collections = config.collections || [];
411
+
412
+ // Log the final result
413
+ const allCollections = config.collections || [];
414
+ const fromCollectionsDir = allCollections.filter((c: any) => !c._isFromTablesDir).length;
415
+ const fromTablesDir = allCollections.filter((c: any) => c._isFromTablesDir).length;
416
+ const totalLoaded = allCollections.length;
417
+
418
+ if (totalLoaded > 0) {
419
+ if (fromTablesDir > 0) {
420
+ MessageFormatter.success(`Successfully loaded ${totalLoaded} items total: ${fromCollectionsDir} from collections/ and ${fromTablesDir} from tables/`, { prefix: "Config" });
421
+ } else {
422
+ MessageFormatter.success(`Successfully loaded ${totalLoaded} collections from collections/`, { prefix: "Config" });
423
+ }
424
+ }
425
+
426
+ // Log successful config loading
427
+ if (actualConfigPath) {
428
+ MessageFormatter.success(`Loaded config from: ${actualConfigPath}`, { prefix: "Config" });
429
+ }
430
+
431
+ // Validate configuration if requested
432
+ if (validate) {
433
+ let validation = validateCollectionsTablesConfig(config);
434
+
435
+ // In strict mode, treat warnings as errors
436
+ if (strictMode && validation.warnings.length > 0) {
437
+ validation = {
438
+ ...validation,
439
+ isValid: false,
440
+ errors: [...validation.errors, ...validation.warnings.map(w => ({ ...w, severity: "error" as const }))],
441
+ warnings: []
442
+ };
443
+ }
444
+
445
+ // Report validation results if requested
446
+ if (reportValidation) {
447
+ reportValidationResults(validation, { verbose: true });
448
+ }
449
+
450
+ // Throw error if validation fails in strict mode
451
+ if (strictMode && !validation.isValid) {
452
+ throw new Error(`Configuration validation failed in strict mode. Found ${validation.errors.length} validation errors.`);
453
+ }
454
+ }
455
+
456
+ return config;
457
+ };