@njdamstra/appwrite-utils-cli 1.8.9 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) 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 +85 -35
  25. package/dist/collections/indexes.js +2 -4
  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 +90 -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 +64 -10
  44. package/dist/main.js +130 -177
  45. package/dist/migrations/afterImportActions.js +2 -3
  46. package/dist/migrations/appwriteToX.d.ts +97 -1
  47. package/dist/migrations/appwriteToX.js +9 -7
  48. package/dist/migrations/comprehensiveTransfer.js +3 -5
  49. package/dist/migrations/dataLoader.d.ts +194 -2
  50. package/dist/migrations/dataLoader.js +2 -5
  51. package/dist/migrations/importController.js +3 -4
  52. package/dist/migrations/importDataActions.js +3 -3
  53. package/dist/migrations/relationships.js +1 -2
  54. package/dist/migrations/services/DataTransformationService.js +2 -2
  55. package/dist/migrations/services/FileHandlerService.js +1 -1
  56. package/dist/migrations/services/ImportOrchestrator.js +4 -4
  57. package/dist/migrations/services/RateLimitManager.js +1 -1
  58. package/dist/migrations/services/RelationshipResolver.js +1 -1
  59. package/dist/migrations/services/UserMappingService.js +1 -1
  60. package/dist/migrations/services/ValidationService.js +1 -1
  61. package/dist/migrations/transfer.d.ts +8 -4
  62. package/dist/migrations/transfer.js +106 -55
  63. package/dist/migrations/yaml/YamlImportConfigLoader.js +1 -1
  64. package/dist/migrations/yaml/YamlImportIntegration.js +2 -2
  65. package/dist/migrations/yaml/generateImportSchemas.js +1 -1
  66. package/dist/setupCommands.d.ts +1 -1
  67. package/dist/setupCommands.js +5 -6
  68. package/dist/setupController.js +1 -1
  69. package/dist/shared/backupTracking.d.ts +1 -1
  70. package/dist/shared/backupTracking.js +2 -2
  71. package/dist/shared/confirmationDialogs.js +1 -1
  72. package/dist/shared/migrationHelpers.d.ts +1 -1
  73. package/dist/shared/migrationHelpers.js +3 -3
  74. package/dist/shared/operationQueue.d.ts +1 -1
  75. package/dist/shared/operationQueue.js +2 -3
  76. package/dist/shared/operationsTable.d.ts +1 -1
  77. package/dist/shared/operationsTable.js +2 -2
  78. package/dist/shared/progressManager.js +1 -1
  79. package/dist/shared/selectionDialogs.js +9 -8
  80. package/dist/storage/methods.js +4 -4
  81. package/dist/storage/schemas.d.ts +386 -2
  82. package/dist/tables/indexManager.d.ts +65 -0
  83. package/dist/tables/indexManager.js +294 -0
  84. package/dist/types.d.ts +2 -2
  85. package/dist/types.js +1 -1
  86. package/dist/users/methods.js +2 -3
  87. package/dist/utils/configMigration.js +1 -1
  88. package/dist/utils/index.d.ts +1 -1
  89. package/dist/utils/index.js +1 -1
  90. package/dist/utils/loadConfigs.d.ts +2 -2
  91. package/dist/utils/loadConfigs.js +6 -7
  92. package/dist/utils/setupFiles.js +5 -7
  93. package/dist/utilsController.d.ts +15 -8
  94. package/dist/utilsController.js +57 -28
  95. package/package.json +8 -4
  96. package/src/adapters/index.ts +8 -34
  97. package/src/backups/operations/bucketBackup.ts +2 -2
  98. package/src/backups/operations/collectionBackup.ts +4 -4
  99. package/src/backups/operations/comprehensiveBackup.ts +3 -3
  100. package/src/backups/tracking/centralizedTracking.ts +3 -3
  101. package/src/cli/commands/configCommands.ts +72 -8
  102. package/src/cli/commands/databaseCommands.ts +161 -9
  103. package/src/cli/commands/functionCommands.ts +4 -3
  104. package/src/cli/commands/importFileCommands.ts +815 -0
  105. package/src/cli/commands/schemaCommands.ts +3 -3
  106. package/src/cli/commands/storageCommands.ts +2 -3
  107. package/src/cli/commands/transferCommands.ts +3 -6
  108. package/src/collections/attributes.ts +155 -39
  109. package/src/collections/indexes.ts +5 -7
  110. package/src/collections/methods.ts +115 -150
  111. package/src/collections/tableOperations.ts +92 -21
  112. package/src/collections/transferOperations.ts +4 -5
  113. package/src/collections/wipeOperations.ts +154 -51
  114. package/src/databases/methods.ts +2 -2
  115. package/src/databases/setup.ts +2 -2
  116. package/src/examples/yamlTerminologyExample.ts +2 -2
  117. package/src/functions/deployments.ts +6 -5
  118. package/src/functions/fnConfigDiscovery.ts +2 -2
  119. package/src/functions/methods.ts +19 -6
  120. package/src/init.ts +1 -1
  121. package/src/interactiveCLI.ts +78 -13
  122. package/src/main.ts +143 -287
  123. package/src/migrations/afterImportActions.ts +2 -3
  124. package/src/migrations/appwriteToX.ts +12 -8
  125. package/src/migrations/comprehensiveTransfer.ts +6 -6
  126. package/src/migrations/dataLoader.ts +2 -5
  127. package/src/migrations/importController.ts +3 -4
  128. package/src/migrations/importDataActions.ts +3 -3
  129. package/src/migrations/relationships.ts +1 -2
  130. package/src/migrations/services/DataTransformationService.ts +2 -2
  131. package/src/migrations/services/FileHandlerService.ts +1 -1
  132. package/src/migrations/services/ImportOrchestrator.ts +4 -4
  133. package/src/migrations/services/RateLimitManager.ts +1 -1
  134. package/src/migrations/services/RelationshipResolver.ts +1 -1
  135. package/src/migrations/services/UserMappingService.ts +1 -1
  136. package/src/migrations/services/ValidationService.ts +1 -1
  137. package/src/migrations/transfer.ts +126 -83
  138. package/src/migrations/yaml/YamlImportConfigLoader.ts +1 -1
  139. package/src/migrations/yaml/YamlImportIntegration.ts +2 -2
  140. package/src/migrations/yaml/generateImportSchemas.ts +1 -1
  141. package/src/setupCommands.ts +5 -6
  142. package/src/setupController.ts +1 -1
  143. package/src/shared/backupTracking.ts +3 -3
  144. package/src/shared/confirmationDialogs.ts +1 -1
  145. package/src/shared/migrationHelpers.ts +4 -4
  146. package/src/shared/operationQueue.ts +3 -4
  147. package/src/shared/operationsTable.ts +3 -3
  148. package/src/shared/progressManager.ts +1 -1
  149. package/src/shared/selectionDialogs.ts +9 -8
  150. package/src/storage/methods.ts +4 -4
  151. package/src/tables/indexManager.ts +409 -0
  152. package/src/types.ts +2 -2
  153. package/src/users/methods.ts +2 -3
  154. package/src/utils/configMigration.ts +1 -1
  155. package/src/utils/index.ts +1 -1
  156. package/src/utils/loadConfigs.ts +15 -7
  157. package/src/utils/setupFiles.ts +5 -7
  158. package/src/utilsController.ts +86 -32
  159. package/dist/adapters/AdapterFactory.d.ts +0 -94
  160. package/dist/adapters/AdapterFactory.js +0 -405
  161. package/dist/adapters/DatabaseAdapter.d.ts +0 -233
  162. package/dist/adapters/DatabaseAdapter.js +0 -50
  163. package/dist/adapters/LegacyAdapter.d.ts +0 -50
  164. package/dist/adapters/LegacyAdapter.js +0 -612
  165. package/dist/adapters/TablesDBAdapter.d.ts +0 -45
  166. package/dist/adapters/TablesDBAdapter.js +0 -571
  167. package/dist/config/ConfigManager.d.ts +0 -445
  168. package/dist/config/ConfigManager.js +0 -625
  169. package/dist/config/configMigration.d.ts +0 -87
  170. package/dist/config/configMigration.js +0 -390
  171. package/dist/config/configValidation.d.ts +0 -66
  172. package/dist/config/configValidation.js +0 -358
  173. package/dist/config/index.d.ts +0 -8
  174. package/dist/config/index.js +0 -7
  175. package/dist/config/services/ConfigDiscoveryService.d.ts +0 -126
  176. package/dist/config/services/ConfigDiscoveryService.js +0 -374
  177. package/dist/config/services/ConfigLoaderService.d.ts +0 -129
  178. package/dist/config/services/ConfigLoaderService.js +0 -540
  179. package/dist/config/services/ConfigMergeService.d.ts +0 -208
  180. package/dist/config/services/ConfigMergeService.js +0 -308
  181. package/dist/config/services/ConfigValidationService.d.ts +0 -214
  182. package/dist/config/services/ConfigValidationService.js +0 -310
  183. package/dist/config/services/SessionAuthService.d.ts +0 -225
  184. package/dist/config/services/SessionAuthService.js +0 -456
  185. package/dist/config/services/__tests__/ConfigMergeService.test.d.ts +0 -1
  186. package/dist/config/services/__tests__/ConfigMergeService.test.js +0 -271
  187. package/dist/config/services/index.d.ts +0 -13
  188. package/dist/config/services/index.js +0 -10
  189. package/dist/config/yamlConfig.d.ts +0 -722
  190. package/dist/config/yamlConfig.js +0 -702
  191. package/dist/functions/pathResolution.d.ts +0 -37
  192. package/dist/functions/pathResolution.js +0 -185
  193. package/dist/shared/attributeMapper.d.ts +0 -20
  194. package/dist/shared/attributeMapper.js +0 -203
  195. package/dist/shared/errorUtils.d.ts +0 -54
  196. package/dist/shared/errorUtils.js +0 -95
  197. package/dist/shared/functionManager.d.ts +0 -48
  198. package/dist/shared/functionManager.js +0 -336
  199. package/dist/shared/indexManager.d.ts +0 -24
  200. package/dist/shared/indexManager.js +0 -151
  201. package/dist/shared/jsonSchemaGenerator.d.ts +0 -50
  202. package/dist/shared/jsonSchemaGenerator.js +0 -290
  203. package/dist/shared/logging.d.ts +0 -61
  204. package/dist/shared/logging.js +0 -116
  205. package/dist/shared/messageFormatter.d.ts +0 -39
  206. package/dist/shared/messageFormatter.js +0 -162
  207. package/dist/shared/pydanticModelGenerator.d.ts +0 -17
  208. package/dist/shared/pydanticModelGenerator.js +0 -615
  209. package/dist/shared/schemaGenerator.d.ts +0 -40
  210. package/dist/shared/schemaGenerator.js +0 -556
  211. package/dist/utils/ClientFactory.d.ts +0 -87
  212. package/dist/utils/ClientFactory.js +0 -212
  213. package/dist/utils/configDiscovery.d.ts +0 -78
  214. package/dist/utils/configDiscovery.js +0 -472
  215. package/dist/utils/constantsGenerator.d.ts +0 -31
  216. package/dist/utils/constantsGenerator.js +0 -321
  217. package/dist/utils/dataConverters.d.ts +0 -46
  218. package/dist/utils/dataConverters.js +0 -139
  219. package/dist/utils/directoryUtils.d.ts +0 -22
  220. package/dist/utils/directoryUtils.js +0 -59
  221. package/dist/utils/getClientFromConfig.d.ts +0 -39
  222. package/dist/utils/getClientFromConfig.js +0 -199
  223. package/dist/utils/helperFunctions.d.ts +0 -63
  224. package/dist/utils/helperFunctions.js +0 -156
  225. package/dist/utils/pathResolvers.d.ts +0 -53
  226. package/dist/utils/pathResolvers.js +0 -72
  227. package/dist/utils/projectConfig.d.ts +0 -119
  228. package/dist/utils/projectConfig.js +0 -171
  229. package/dist/utils/retryFailedPromises.d.ts +0 -2
  230. package/dist/utils/retryFailedPromises.js +0 -23
  231. package/dist/utils/sessionAuth.d.ts +0 -48
  232. package/dist/utils/sessionAuth.js +0 -164
  233. package/dist/utils/typeGuards.d.ts +0 -35
  234. package/dist/utils/typeGuards.js +0 -57
  235. package/dist/utils/validationRules.d.ts +0 -43
  236. package/dist/utils/validationRules.js +0 -42
  237. package/dist/utils/versionDetection.d.ts +0 -58
  238. package/dist/utils/versionDetection.js +0 -251
  239. package/dist/utils/yamlConverter.d.ts +0 -100
  240. package/dist/utils/yamlConverter.js +0 -428
  241. package/dist/utils/yamlLoader.d.ts +0 -70
  242. package/dist/utils/yamlLoader.js +0 -267
  243. package/src/adapters/AdapterFactory.ts +0 -510
  244. package/src/adapters/DatabaseAdapter.ts +0 -306
  245. package/src/adapters/LegacyAdapter.ts +0 -841
  246. package/src/adapters/TablesDBAdapter.ts +0 -773
  247. package/src/config/ConfigManager.ts +0 -808
  248. package/src/config/README.md +0 -274
  249. package/src/config/configMigration.ts +0 -575
  250. package/src/config/configValidation.ts +0 -445
  251. package/src/config/index.ts +0 -10
  252. package/src/config/services/ConfigDiscoveryService.ts +0 -463
  253. package/src/config/services/ConfigLoaderService.ts +0 -740
  254. package/src/config/services/ConfigMergeService.ts +0 -388
  255. package/src/config/services/ConfigValidationService.ts +0 -394
  256. package/src/config/services/SessionAuthService.ts +0 -565
  257. package/src/config/services/__tests__/ConfigMergeService.test.ts +0 -351
  258. package/src/config/services/index.ts +0 -29
  259. package/src/config/yamlConfig.ts +0 -761
  260. package/src/functions/pathResolution.ts +0 -227
  261. package/src/shared/attributeMapper.ts +0 -229
  262. package/src/shared/errorUtils.ts +0 -110
  263. package/src/shared/functionManager.ts +0 -525
  264. package/src/shared/indexManager.ts +0 -254
  265. package/src/shared/jsonSchemaGenerator.ts +0 -383
  266. package/src/shared/logging.ts +0 -149
  267. package/src/shared/messageFormatter.ts +0 -208
  268. package/src/shared/pydanticModelGenerator.ts +0 -618
  269. package/src/shared/schemaGenerator.ts +0 -644
  270. package/src/utils/ClientFactory.ts +0 -240
  271. package/src/utils/configDiscovery.ts +0 -557
  272. package/src/utils/constantsGenerator.ts +0 -369
  273. package/src/utils/dataConverters.ts +0 -159
  274. package/src/utils/directoryUtils.ts +0 -61
  275. package/src/utils/getClientFromConfig.ts +0 -257
  276. package/src/utils/helperFunctions.ts +0 -228
  277. package/src/utils/pathResolvers.ts +0 -81
  278. package/src/utils/projectConfig.ts +0 -299
  279. package/src/utils/retryFailedPromises.ts +0 -29
  280. package/src/utils/sessionAuth.ts +0 -230
  281. package/src/utils/typeGuards.ts +0 -65
  282. package/src/utils/validationRules.ts +0 -88
  283. package/src/utils/versionDetection.ts +0 -292
  284. package/src/utils/yamlConverter.ts +0 -542
  285. package/src/utils/yamlLoader.ts +0 -371
@@ -1,17 +1,16 @@
1
1
  import { converterFunctions, tryAwaitWithRetry } from "@njdamstra/appwrite-utils";
2
2
  import { Client, Databases, IndexType, Query, Storage, Users, } from "node-appwrite";
3
3
  import { InputFile } from "node-appwrite/file";
4
- import { getAppwriteClient } from "../utils/helperFunctions.js";
4
+ import { getAppwriteClient } from "@njdamstra/appwrite-utils-helpers";
5
5
  // Legacy attribute helpers retained only for local-to-local flows if needed
6
6
  import { parseAttribute } from "@njdamstra/appwrite-utils";
7
7
  import chalk from "chalk";
8
8
  import { fetchAllCollections } from "../collections/methods.js";
9
- import { MessageFormatter } from "../shared/messageFormatter.js";
10
- import { LegacyAdapter } from "../adapters/LegacyAdapter.js";
9
+ import { MessageFormatter, mapToCreateAttributeParams } from "@njdamstra/appwrite-utils-helpers";
11
10
  import { ProgressManager } from "../shared/progressManager.js";
12
- import { getClient, getAdapter } from "../utils/getClientFromConfig.js";
11
+ import { getClient, getAdapter } from "@njdamstra/appwrite-utils-helpers";
13
12
  import { diffTableColumns } from "../collections/tableOperations.js";
14
- import { mapToCreateAttributeParams } from "../shared/attributeMapper.js";
13
+ import { LegacyAdapter } from "@njdamstra/appwrite-utils-helpers";
15
14
  export const transferStorageLocalToLocal = async (storage, fromBucketId, toBucketId) => {
16
15
  MessageFormatter.info(`Transferring files from ${fromBucketId} to ${toBucketId}`, { prefix: "Transfer" });
17
16
  let lastFileId;
@@ -130,51 +129,96 @@ export const transferStorageLocalToRemote = async (localStorage, endpoint, proje
130
129
  // Document transfer functions moved to collections/methods.ts with enhanced UX
131
130
  // Remote document transfer functions moved to collections/methods.ts with enhanced UX
132
131
  /**
133
- * Transfers all collections and documents from one local database to another local database.
132
+ * Transfers all tables/collections and documents from one local database to another local database.
133
+ * Uses the DatabaseAdapter for unified TablesDB / legacy support.
134
134
  *
135
- * @param {Databases} localDb - The local database instance.
135
+ * @param {Databases} localDb - The local database instance (kept for signature compat).
136
136
  * @param {string} fromDbId - The ID of the source database.
137
137
  * @param {string} targetDbId - The ID of the target database.
138
+ * @param {string[]} collectionIds - Optional filter: specific table/collection IDs to transfer. undefined = all, empty array = none.
139
+ * @param {DatabaseAdapter} adapter - The database adapter (TablesDB or Legacy).
138
140
  * @return {Promise<void>} A promise that resolves when the transfer is complete.
139
141
  */
140
- export const transferDatabaseLocalToLocal = async (localDb, fromDbId, targetDbId) => {
141
- MessageFormatter.info(`Starting database transfer from ${fromDbId} to ${targetDbId}`, { prefix: "Transfer" });
142
- // Get all collections from source database
143
- const sourceCollections = await fetchAllCollections(fromDbId, localDb);
144
- MessageFormatter.info(`Found ${sourceCollections.length} collections in source database`, { prefix: "Transfer" });
145
- // Process each collection
146
- for (const collection of sourceCollections) {
147
- MessageFormatter.processing(`Processing collection: ${collection.name} (${collection.$id})`, { prefix: "Transfer" });
142
+ export const transferDatabaseLocalToLocal = async (localDb, fromDbId, targetDbId, collectionIds, adapter) => {
143
+ // If no adapter provided, fall back to creating a LegacyAdapter from the Databases client
144
+ const dbAdapter = adapter || new LegacyAdapter(localDb.client);
145
+ MessageFormatter.info(`Starting database transfer from ${fromDbId} to ${targetDbId} (mode: ${dbAdapter.getApiMode()})`, { prefix: "Transfer" });
146
+ // Get all tables/collections from source database via adapter
147
+ const sourceListRes = await dbAdapter.listTables({ databaseId: fromDbId, queries: [Query.limit(500)] });
148
+ let sourceTables = sourceListRes.tables || sourceListRes.collections || sourceListRes.data || [];
149
+ // Filter by collectionIds if provided (match by $id or by name)
150
+ if (collectionIds !== undefined) {
151
+ if (collectionIds.length === 0) {
152
+ MessageFormatter.info("No tables/collections selected for transfer, skipping.", { prefix: "Transfer" });
153
+ return;
154
+ }
155
+ const idSet = new Set(collectionIds);
156
+ sourceTables = sourceTables.filter((c) => idSet.has(c.$id) || idSet.has(c.name));
157
+ }
158
+ MessageFormatter.info(`Found ${sourceTables.length} tables/collections in source database`, { prefix: "Transfer" });
159
+ // Process each table/collection
160
+ for (const table of sourceTables) {
161
+ MessageFormatter.processing(`Processing table: ${table.name} (${table.$id})`, { prefix: "Transfer" });
148
162
  try {
149
- // Create or update collection in target
150
- let targetCollection;
151
- const existingCollection = await tryAwaitWithRetry(async () => localDb.listCollections(targetDbId, [
152
- Query.equal("$id", collection.$id),
153
- ]));
154
- if (existingCollection.collections.length > 0) {
155
- targetCollection = existingCollection.collections[0];
156
- MessageFormatter.info(`Collection ${collection.name} exists in target database`, { prefix: "Transfer" });
157
- // Update collection if needed
158
- if (targetCollection.name !== collection.name ||
159
- targetCollection.$permissions !== collection.$permissions ||
160
- targetCollection.documentSecurity !== collection.documentSecurity ||
161
- targetCollection.enabled !== collection.enabled) {
162
- targetCollection = await tryAwaitWithRetry(async () => localDb.updateCollection(targetDbId, collection.$id, collection.name, collection.$permissions, collection.documentSecurity, collection.enabled));
163
- MessageFormatter.success(`Collection ${collection.name} updated`, { prefix: "Transfer" });
163
+ // Check if table exists in target via adapter
164
+ let targetTableId = table.$id;
165
+ let targetTableData;
166
+ try {
167
+ const existingRes = await dbAdapter.getTable({ databaseId: targetDbId, tableId: table.$id });
168
+ targetTableData = existingRes.data || (existingRes.tables && existingRes.tables[0]);
169
+ if (targetTableData) {
170
+ MessageFormatter.info(`Table ${table.name} exists in target database`, { prefix: "Transfer" });
171
+ // Update table if needed
172
+ const securityField = table.rowSecurity ?? table.documentSecurity ?? false;
173
+ const targetSecurity = targetTableData.rowSecurity ?? targetTableData.documentSecurity ?? false;
174
+ if (targetTableData.name !== table.name ||
175
+ JSON.stringify(targetTableData.$permissions) !== JSON.stringify(table.$permissions) ||
176
+ targetSecurity !== securityField ||
177
+ targetTableData.enabled !== table.enabled) {
178
+ await tryAwaitWithRetry(async () => dbAdapter.updateTable({
179
+ databaseId: targetDbId,
180
+ id: table.$id,
181
+ name: table.name,
182
+ permissions: table.$permissions,
183
+ documentSecurity: table.documentSecurity,
184
+ rowSecurity: table.rowSecurity,
185
+ enabled: table.enabled,
186
+ }));
187
+ MessageFormatter.success(`Table ${table.name} updated`, { prefix: "Transfer" });
188
+ }
164
189
  }
165
190
  }
166
- else {
167
- MessageFormatter.progress(`Creating collection ${collection.name} in target database...`, { prefix: "Transfer" });
168
- targetCollection = await tryAwaitWithRetry(async () => localDb.createCollection(targetDbId, collection.$id, collection.name, collection.$permissions, collection.documentSecurity, collection.enabled));
191
+ catch {
192
+ // Table does not exist in target, create it
193
+ targetTableData = null;
169
194
  }
170
- // Create attributes via local adapter (wrap the existing client)
171
- const localAdapter = new LegacyAdapter(localDb.client);
172
- MessageFormatter.info(`Creating attributes for ${collection.name} via adapter...`, { prefix: 'Transfer' });
173
- const uniformAttrs = collection.attributes.map((attr) => parseAttribute(attr));
195
+ if (!targetTableData) {
196
+ MessageFormatter.progress(`Creating table ${table.name} in target database...`, { prefix: "Transfer" });
197
+ const createRes = await tryAwaitWithRetry(async () => dbAdapter.createTable({
198
+ databaseId: targetDbId,
199
+ id: table.$id,
200
+ name: table.name,
201
+ permissions: table.$permissions,
202
+ documentSecurity: table.documentSecurity,
203
+ rowSecurity: table.rowSecurity,
204
+ enabled: table.enabled,
205
+ }));
206
+ targetTableData = createRes.data || (createRes.tables && createRes.tables[0]);
207
+ }
208
+ // Create attributes via adapter
209
+ MessageFormatter.info(`Creating attributes for ${table.name} via adapter...`, { prefix: 'Transfer' });
210
+ // Fetch existing attributes in target to skip already-created ones
211
+ const targetTableRes = await dbAdapter.getTable({ databaseId: targetDbId, tableId: targetTableId });
212
+ const targetInfo = targetTableRes.data || (targetTableRes.tables && targetTableRes.tables[0]);
213
+ const existingAttrs = targetInfo?.attributes || targetInfo?.columns || [];
214
+ const existingKeys = new Set(existingAttrs.map((a) => a.key || a.$id));
215
+ const uniformAttrs = (table.attributes || []).map((attr) => parseAttribute(attr));
174
216
  const nonRel = uniformAttrs.filter((a) => a.type !== 'relationship');
175
217
  for (const attr of nonRel) {
176
- const params = mapToCreateAttributeParams(attr, { databaseId: targetDbId, tableId: targetCollection.$id });
177
- await localAdapter.createAttribute(params);
218
+ if (existingKeys.has(attr.key))
219
+ continue;
220
+ const params = mapToCreateAttributeParams(attr, { databaseId: targetDbId, tableId: targetTableId });
221
+ await dbAdapter.createAttribute(params);
178
222
  await new Promise((r) => setTimeout(r, 150));
179
223
  }
180
224
  // Wait for attributes to become available
@@ -184,8 +228,9 @@ export const transferDatabaseLocalToLocal = async (localDb, fromDbId, targetDbId
184
228
  let lastStatus = '';
185
229
  while (Date.now() - start < maxWait) {
186
230
  try {
187
- const tableRes = await localAdapter.getTable({ databaseId: targetDbId, tableId: targetCollection.$id });
188
- const attrs = tableRes.attributes || tableRes.columns || [];
231
+ const tableRes = await dbAdapter.getTable({ databaseId: targetDbId, tableId: targetTableId });
232
+ const tInfo = tableRes.data || (tableRes.tables && tableRes.tables[0]);
233
+ const attrs = tInfo?.attributes || tInfo?.columns || [];
189
234
  const found = attrs.find((a) => a.key === attr.key);
190
235
  if (found) {
191
236
  if (found.status === 'available')
@@ -208,16 +253,18 @@ export const transferDatabaseLocalToLocal = async (localDb, fromDbId, targetDbId
208
253
  // Relationship attributes
209
254
  const rels = uniformAttrs.filter((a) => a.type === 'relationship');
210
255
  for (const attr of rels) {
211
- const params = mapToCreateAttributeParams(attr, { databaseId: targetDbId, tableId: targetCollection.$id });
212
- await localAdapter.createAttribute(params);
256
+ if (existingKeys.has(attr.key))
257
+ continue;
258
+ const params = mapToCreateAttributeParams(attr, { databaseId: targetDbId, tableId: targetTableId });
259
+ await dbAdapter.createAttribute(params);
213
260
  await new Promise((r) => setTimeout(r, 150));
214
261
  }
215
262
  // Handle indexes via adapter (create or update)
216
- for (const idx of collection.indexes) {
263
+ for (const idx of (table.indexes || [])) {
217
264
  try {
218
- await localAdapter.createIndex({
265
+ await dbAdapter.createIndex({
219
266
  databaseId: targetDbId,
220
- tableId: targetCollection.$id,
267
+ tableId: targetTableId,
221
268
  key: idx.key,
222
269
  type: idx.type,
223
270
  attributes: idx.attributes,
@@ -229,10 +276,10 @@ export const transferDatabaseLocalToLocal = async (localDb, fromDbId, targetDbId
229
276
  catch (e) {
230
277
  // Try update path by deleting and recreating if necessary
231
278
  try {
232
- await localAdapter.deleteIndex({ databaseId: targetDbId, tableId: targetCollection.$id, key: idx.key });
233
- await localAdapter.createIndex({
279
+ await dbAdapter.deleteIndex({ databaseId: targetDbId, tableId: targetTableId, key: idx.key });
280
+ await dbAdapter.createIndex({
234
281
  databaseId: targetDbId,
235
- tableId: targetCollection.$id,
282
+ tableId: targetTableId,
236
283
  key: idx.key,
237
284
  type: idx.type,
238
285
  attributes: idx.attributes,
@@ -246,20 +293,24 @@ export const transferDatabaseLocalToLocal = async (localDb, fromDbId, targetDbId
246
293
  }
247
294
  }
248
295
  }
249
- // Transfer documents
250
- const { transferDocumentsBetweenDbsLocalToLocal } = await import("../collections/methods.js");
251
- await transferDocumentsBetweenDbsLocalToLocal(localDb, fromDbId, targetDbId, collection.$id, targetCollection.$id);
296
+ // Transfer documents/rows via adapter
297
+ const { transferDocumentsBetweenDbsLocalToLocal } = await import("../collections/transferOperations.js");
298
+ await transferDocumentsBetweenDbsLocalToLocal(dbAdapter, fromDbId, targetDbId, table.$id, targetTableId);
252
299
  }
253
300
  catch (error) {
254
- MessageFormatter.error(`Error processing collection ${collection.name}`, error instanceof Error ? error : new Error(String(error)), { prefix: "Transfer" });
301
+ MessageFormatter.error(`Error processing table ${table.name}`, error instanceof Error ? error : new Error(String(error)), { prefix: "Transfer" });
255
302
  }
256
303
  }
257
304
  };
258
- export const transferDatabaseLocalToRemote = async (localDb, endpoint, projectId, apiKey, fromDbId, toDbId) => {
305
+ export const transferDatabaseLocalToRemote = async (localDb, endpoint, projectId, apiKey, fromDbId, toDbId, collectionIds) => {
259
306
  const client = getAppwriteClient(endpoint, projectId, apiKey);
260
307
  const remoteDb = new Databases(client);
261
308
  // Get all collections from source database
262
- const sourceCollections = await fetchAllCollections(fromDbId, localDb);
309
+ let sourceCollections = await fetchAllCollections(fromDbId, localDb);
310
+ if (collectionIds && collectionIds.length > 0) {
311
+ const idSet = new Set(collectionIds);
312
+ sourceCollections = sourceCollections.filter((c) => idSet.has(c.$id));
313
+ }
263
314
  MessageFormatter.info(`Found ${sourceCollections.length} collections in source database`, { prefix: "Transfer" });
264
315
  // Process each collection
265
316
  for (const collection of sourceCollections) {
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  import path from "path";
3
3
  import fs from "fs";
4
4
  import yaml from "js-yaml";
5
- import { logger } from "../../shared/logging.js";
5
+ import { logger } from '@njdamstra/appwrite-utils-helpers';
6
6
  // YAML Import Configuration Schema
7
7
  export const YamlImportConfigSchema = z.object({
8
8
  source: z.object({
@@ -1,7 +1,7 @@
1
1
  import { YamlImportConfigLoader } from "./YamlImportConfigLoader.js";
2
2
  import { createImportSchemas, createImportExamples } from "./generateImportSchemas.js";
3
- import { logger } from "../../shared/logging.js";
4
- import { normalizeYamlData, usesTableTerminology, convertTerminology } from "../../utils/yamlConverter.js";
3
+ import { logger } from '@njdamstra/appwrite-utils-helpers';
4
+ import { normalizeYamlData, usesTableTerminology, convertTerminology } from "@njdamstra/appwrite-utils-helpers";
5
5
  import path from "path";
6
6
  import fs from "fs";
7
7
  import yaml from "js-yaml";
@@ -1,6 +1,6 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
- import { logger } from "../../shared/logging.js";
3
+ import { logger } from '@njdamstra/appwrite-utils-helpers';
4
4
  /**
5
5
  * Generates JSON Schema for YAML import configurations.
6
6
  * Provides IntelliSense support for YAML files in IDEs.
@@ -1,4 +1,4 @@
1
- import { type ApiMode } from "./utils/versionDetection.js";
1
+ import { type ApiMode } from "@njdamstra/appwrite-utils-helpers";
2
2
  /**
3
3
  * Terminology configuration for API mode-specific naming
4
4
  */
@@ -1,12 +1,11 @@
1
1
  import { mkdirSync, writeFileSync, existsSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import { ulid } from "ulidx";
4
- import { MessageFormatter } from "./shared/messageFormatter.js";
5
- import { detectAppwriteVersionCached, fetchServerVersion, isVersionAtLeast } from "./utils/versionDetection.js";
6
- import { loadAppwriteProjectConfig, findAppwriteProjectConfig, isTablesDBProject } from "./utils/projectConfig.js";
7
- import { findYamlConfig, generateYamlConfigTemplate } from "./config/yamlConfig.js";
8
- import { loadYamlConfig } from "./config/yamlConfig.js";
9
- import { hasSessionAuth } from "./utils/sessionAuth.js";
4
+ import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
5
+ import { detectAppwriteVersionCached, fetchServerVersion, isVersionAtLeast } from "@njdamstra/appwrite-utils-helpers";
6
+ import { loadAppwriteProjectConfig, findAppwriteProjectConfig, isTablesDBProject } from "@njdamstra/appwrite-utils-helpers";
7
+ import { findYamlConfig, generateYamlConfigTemplate, loadYamlConfig } from "@njdamstra/appwrite-utils-helpers";
8
+ import { hasSessionAuth } from "@njdamstra/appwrite-utils-helpers";
10
9
  /**
11
10
  * Get terminology configuration based on API mode
12
11
  */
@@ -2,7 +2,7 @@ import { setupDirsFiles } from "./utils/setupFiles.js";
2
2
  import { loadConfig } from "./utils/loadConfigs.js";
3
3
  import path from "path";
4
4
  import fs from "fs";
5
- import { MessageFormatter } from "./shared/messageFormatter.js";
5
+ import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
6
6
  export class SetupController {
7
7
  currentDir;
8
8
  config = null;
@@ -1,4 +1,4 @@
1
- import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
1
+ import type { DatabaseAdapter } from "@njdamstra/appwrite-utils-helpers";
2
2
  import { type BackupMetadata } from "./backupMetadataSchema.js";
3
3
  /**
4
4
  * Creates the backup tracking table in the specified database
@@ -1,5 +1,5 @@
1
- import { logger } from "./logging.js";
2
- import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
1
+ import { logger } from '@njdamstra/appwrite-utils-helpers';
2
+ import { tryAwaitWithRetry } from "@njdamstra/appwrite-utils-helpers";
3
3
  import { Query, ID } from "node-appwrite";
4
4
  import { BACKUP_TABLE_ID, BACKUP_TABLE_NAME, BackupMetadataSchema } from "./backupMetadataSchema.js";
5
5
  /**
@@ -1,6 +1,6 @@
1
1
  import inquirer from "inquirer";
2
2
  import chalk from "chalk";
3
- import { MessageFormatter } from "./messageFormatter.js";
3
+ import { MessageFormatter } from '@njdamstra/appwrite-utils-helpers';
4
4
  export class ConfirmationDialogs {
5
5
  /**
6
6
  * Shows a confirmation dialog for destructive operations
@@ -1,6 +1,6 @@
1
1
  import { type Databases } from "node-appwrite";
2
2
  import { z } from "zod";
3
- import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
3
+ import type { DatabaseAdapter } from "@njdamstra/appwrite-utils-helpers";
4
4
  /**
5
5
  * Object that contains the context for an action that needs to be executed after import
6
6
  * Used in the afterImportActionsDefinitions
@@ -2,10 +2,10 @@ import { ID, Query } from "node-appwrite";
2
2
  import { BatchSchema, OperationSchema } from "../storage/schemas.js";
3
3
  import { AttributeMappingsSchema } from "@njdamstra/appwrite-utils";
4
4
  import { z } from "zod";
5
- import { logger } from "./logging.js";
6
- import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
5
+ import { logger } from '@njdamstra/appwrite-utils-helpers';
6
+ import { tryAwaitWithRetry } from "@njdamstra/appwrite-utils-helpers";
7
7
  import { findOrCreateOperation as findOrCreateOp, updateOperation as updateOp, getOperation as getOp } from "./operationsTable.js";
8
- import { MessageFormatter } from "./messageFormatter.js";
8
+ import { MessageFormatter } from '@njdamstra/appwrite-utils-helpers';
9
9
  /**
10
10
  * Object that contains the context for an action that needs to be executed after import
11
11
  * Used in the afterImportActionsDefinitions
@@ -1,6 +1,6 @@
1
1
  import { type Databases, type Models } from "node-appwrite";
2
2
  import type { Attribute } from "@njdamstra/appwrite-utils";
3
- import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
3
+ import type { DatabaseAdapter } from "@njdamstra/appwrite-utils-helpers";
4
4
  export interface QueuedOperation {
5
5
  type: "attribute";
6
6
  collectionId?: string;
@@ -1,9 +1,8 @@
1
1
  import { Query } from "node-appwrite";
2
2
  import { createOrUpdateAttributeWithStatusCheck } from "../collections/attributes.js";
3
3
  import { fetchAndCacheCollectionByName } from "../collections/methods.js";
4
- import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
5
- import { logger } from "../shared/logging.js";
6
- import { MessageFormatter } from "../shared/messageFormatter.js";
4
+ import { tryAwaitWithRetry } from "@njdamstra/appwrite-utils-helpers";
5
+ import { logger, MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
7
6
  // Global state management
8
7
  export const queuedOperations = [];
9
8
  export const nameToIdMapping = new Map();
@@ -1,4 +1,4 @@
1
- import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
1
+ import type { DatabaseAdapter } from "@njdamstra/appwrite-utils-helpers";
2
2
  import { type OperationRecord } from "./operationsTableSchema.js";
3
3
  /**
4
4
  * Creates the operations tracking table in the specified database
@@ -1,5 +1,5 @@
1
- import { logger } from "./logging.js";
2
- import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
1
+ import { logger } from '@njdamstra/appwrite-utils-helpers';
2
+ import { tryAwaitWithRetry } from "@njdamstra/appwrite-utils-helpers";
3
3
  import { Query, ID } from "node-appwrite";
4
4
  import { OPERATIONS_TABLE_ID, OPERATIONS_TABLE_NAME, OperationRecordSchema, } from "./operationsTableSchema.js";
5
5
  /**
@@ -1,6 +1,6 @@
1
1
  import cliProgress from "cli-progress";
2
2
  import chalk from "chalk";
3
- import { MessageFormatter } from "./messageFormatter.js";
3
+ import { MessageFormatter } from '@njdamstra/appwrite-utils-helpers';
4
4
  export class ProgressManager {
5
5
  static instances = new Map();
6
6
  bar;
@@ -1,7 +1,7 @@
1
1
  import inquirer from "inquirer";
2
2
  import chalk from "chalk";
3
- import { MessageFormatter } from "./messageFormatter.js";
4
- import { logger } from "./logging.js";
3
+ import { MessageFormatter } from '@njdamstra/appwrite-utils-helpers';
4
+ import { logger } from '@njdamstra/appwrite-utils-helpers';
5
5
  /**
6
6
  * Comprehensive selection dialog system for enhanced sync flow
7
7
  *
@@ -186,7 +186,7 @@ export class SelectionDialogs {
186
186
  if (showDatabaseContext) {
187
187
  MessageFormatter.section(`Table Selection for ${databaseName}`);
188
188
  }
189
- const configuredIds = new Set(configuredTables.map(table => table.$id || table.id));
189
+ const configuredIds = new Set(configuredTables.map(table => table.$id || table.id || table.tableId || table.name));
190
190
  let choices = [];
191
191
  if (showSelectAll && availableTables.length > 1) {
192
192
  choices.push({
@@ -196,18 +196,19 @@ export class SelectionDialogs {
196
196
  });
197
197
  }
198
198
  availableTables.forEach(table => {
199
- const isConfigured = configuredIds.has(table.$id);
199
+ const tableId = table.$id || table.id || table.tableId || table.name;
200
+ const isConfigured = configuredIds.has(tableId);
200
201
  const status = isConfigured ? chalk.green('✅') : chalk.blue('○');
201
- const name = `${status} ${table.name} (${table.$id})`;
202
+ const name = `${status} ${table.name} (${tableId})`;
202
203
  if (allowNewOnly && isConfigured) {
203
204
  return; // Skip configured tables if only allowing new ones
204
205
  }
205
206
  choices.push({
206
207
  name,
207
- value: table.$id,
208
+ value: tableId,
208
209
  short: table.name,
209
210
  // Do not preselect anything unless explicitly provided
210
- checked: defaultSelected.includes(table.$id)
211
+ checked: defaultSelected.includes(tableId)
211
212
  });
212
213
  });
213
214
  if (choices.length === 0) {
@@ -231,7 +232,7 @@ export class SelectionDialogs {
231
232
  }]);
232
233
  // Handle select all
233
234
  if (selectedTableIds.includes('__SELECT_ALL__')) {
234
- const allIds = availableTables.map(table => table.$id);
235
+ const allIds = availableTables.map(table => table.$id || table.id || table.tableId || table.name);
235
236
  if (allowNewOnly) {
236
237
  return allIds.filter(id => !configuredIds.has(id));
237
238
  }
@@ -1,15 +1,15 @@
1
1
  import { Compression, Databases, Permission, Query, Role, Storage, } from "node-appwrite";
2
2
  import { tryAwaitWithRetry } from "@njdamstra/appwrite-utils";
3
- import { getClientFromConfig } from "../utils/getClientFromConfig.js";
3
+ import { getClientFromConfig } from "@njdamstra/appwrite-utils-helpers";
4
4
  import { ulid } from "ulidx";
5
5
  import { logOperation } from "../shared/operationLogger.js";
6
6
  import { splitIntoBatches } from "../shared/migrationHelpers.js";
7
- import { retryFailedPromises } from "../utils/retryFailedPromises.js";
7
+ import { retryFailedPromises } from "@njdamstra/appwrite-utils-helpers";
8
8
  import { InputFile } from "node-appwrite/file";
9
- import { MessageFormatter, Messages } from "../shared/messageFormatter.js";
9
+ import { MessageFormatter, Messages } from "@njdamstra/appwrite-utils-helpers";
10
10
  import { ProgressManager } from "../shared/progressManager.js";
11
11
  import { recordBackup } from "../shared/backupTracking.js";
12
- import { AdapterFactory } from "../adapters/AdapterFactory.js";
12
+ import { AdapterFactory } from "@njdamstra/appwrite-utils-helpers";
13
13
  import { createBackupZip } from "./backupCompression.js";
14
14
  export const getStorage = (config) => {
15
15
  const client = getClientFromConfig(config);