appwrite-utils-cli 0.10.86 → 1.0.2

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 (178) hide show
  1. package/.appwrite/.yaml_schemas/appwrite-config.schema.json +380 -0
  2. package/.appwrite/.yaml_schemas/collection.schema.json +255 -0
  3. package/.appwrite/collections/Categories.yaml +182 -0
  4. package/.appwrite/collections/ExampleCollection.yaml +36 -0
  5. package/.appwrite/collections/Posts.yaml +227 -0
  6. package/.appwrite/collections/Users.yaml +149 -0
  7. package/.appwrite/config.yaml +109 -0
  8. package/.appwrite/import/README.md +148 -0
  9. package/.appwrite/import/categories-import.yaml +129 -0
  10. package/.appwrite/import/posts-import.yaml +208 -0
  11. package/.appwrite/import/users-import.yaml +130 -0
  12. package/.appwrite/importData/categories.json +194 -0
  13. package/.appwrite/importData/posts.json +270 -0
  14. package/.appwrite/importData/users.json +220 -0
  15. package/.appwrite/schemas/categories.json +128 -0
  16. package/.appwrite/schemas/exampleCollection.json +52 -0
  17. package/.appwrite/schemas/posts.json +173 -0
  18. package/.appwrite/schemas/users.json +125 -0
  19. package/README.md +264 -33
  20. package/dist/collections/attributes.js +3 -2
  21. package/dist/collections/methods.js +56 -38
  22. package/dist/config/yamlConfig.d.ts +501 -0
  23. package/dist/config/yamlConfig.js +452 -0
  24. package/dist/databases/setup.d.ts +6 -0
  25. package/dist/databases/setup.js +119 -0
  26. package/dist/functions/methods.d.ts +1 -1
  27. package/dist/functions/methods.js +5 -2
  28. package/dist/functions/openapi.d.ts +4 -0
  29. package/dist/functions/openapi.js +60 -0
  30. package/dist/interactiveCLI.d.ts +5 -0
  31. package/dist/interactiveCLI.js +194 -49
  32. package/dist/main.js +91 -30
  33. package/dist/migrations/afterImportActions.js +2 -2
  34. package/dist/migrations/appwriteToX.d.ts +10 -0
  35. package/dist/migrations/appwriteToX.js +15 -4
  36. package/dist/migrations/backup.d.ts +16 -16
  37. package/dist/migrations/dataLoader.d.ts +83 -1
  38. package/dist/migrations/dataLoader.js +4 -4
  39. package/dist/migrations/importController.js +25 -18
  40. package/dist/migrations/importDataActions.js +2 -2
  41. package/dist/migrations/logging.d.ts +9 -1
  42. package/dist/migrations/logging.js +41 -22
  43. package/dist/migrations/migrationHelper.d.ts +4 -4
  44. package/dist/migrations/relationships.js +1 -1
  45. package/dist/migrations/services/DataTransformationService.d.ts +55 -0
  46. package/dist/migrations/services/DataTransformationService.js +158 -0
  47. package/dist/migrations/services/FileHandlerService.d.ts +75 -0
  48. package/dist/migrations/services/FileHandlerService.js +236 -0
  49. package/dist/migrations/services/ImportOrchestrator.d.ts +97 -0
  50. package/dist/migrations/services/ImportOrchestrator.js +488 -0
  51. package/dist/migrations/services/RateLimitManager.d.ts +138 -0
  52. package/dist/migrations/services/RateLimitManager.js +279 -0
  53. package/dist/migrations/services/RelationshipResolver.d.ts +120 -0
  54. package/dist/migrations/services/RelationshipResolver.js +332 -0
  55. package/dist/migrations/services/UserMappingService.d.ts +109 -0
  56. package/dist/migrations/services/UserMappingService.js +277 -0
  57. package/dist/migrations/services/ValidationService.d.ts +74 -0
  58. package/dist/migrations/services/ValidationService.js +260 -0
  59. package/dist/migrations/transfer.d.ts +0 -6
  60. package/dist/migrations/transfer.js +16 -132
  61. package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +384 -0
  62. package/dist/migrations/yaml/YamlImportConfigLoader.js +375 -0
  63. package/dist/migrations/yaml/YamlImportIntegration.d.ts +87 -0
  64. package/dist/migrations/yaml/YamlImportIntegration.js +330 -0
  65. package/dist/migrations/yaml/generateImportSchemas.d.ts +17 -0
  66. package/dist/migrations/yaml/generateImportSchemas.js +575 -0
  67. package/dist/schemas/authUser.d.ts +9 -9
  68. package/dist/shared/attributeManager.d.ts +17 -0
  69. package/dist/shared/attributeManager.js +273 -0
  70. package/dist/shared/confirmationDialogs.d.ts +75 -0
  71. package/dist/shared/confirmationDialogs.js +236 -0
  72. package/dist/shared/functionManager.d.ts +48 -0
  73. package/dist/shared/functionManager.js +322 -0
  74. package/dist/shared/indexManager.d.ts +24 -0
  75. package/dist/shared/indexManager.js +150 -0
  76. package/dist/shared/jsonSchemaGenerator.d.ts +51 -0
  77. package/dist/shared/jsonSchemaGenerator.js +313 -0
  78. package/dist/shared/logging.d.ts +10 -0
  79. package/dist/shared/logging.js +46 -0
  80. package/dist/shared/messageFormatter.d.ts +37 -0
  81. package/dist/shared/messageFormatter.js +152 -0
  82. package/dist/shared/migrationHelpers.d.ts +173 -0
  83. package/dist/shared/migrationHelpers.js +142 -0
  84. package/dist/shared/operationLogger.d.ts +3 -0
  85. package/dist/shared/operationLogger.js +25 -0
  86. package/dist/shared/operationQueue.d.ts +13 -0
  87. package/dist/shared/operationQueue.js +79 -0
  88. package/dist/shared/progressManager.d.ts +62 -0
  89. package/dist/shared/progressManager.js +215 -0
  90. package/dist/shared/schemaGenerator.d.ts +18 -0
  91. package/dist/shared/schemaGenerator.js +523 -0
  92. package/dist/storage/methods.d.ts +3 -1
  93. package/dist/storage/methods.js +144 -55
  94. package/dist/storage/schemas.d.ts +56 -16
  95. package/dist/types.d.ts +2 -2
  96. package/dist/types.js +1 -1
  97. package/dist/users/methods.d.ts +16 -0
  98. package/dist/users/methods.js +276 -0
  99. package/dist/utils/configMigration.d.ts +1 -0
  100. package/dist/utils/configMigration.js +262 -0
  101. package/dist/utils/dataConverters.d.ts +46 -0
  102. package/dist/utils/dataConverters.js +139 -0
  103. package/dist/utils/loadConfigs.d.ts +15 -4
  104. package/dist/utils/loadConfigs.js +379 -51
  105. package/dist/utils/schemaStrings.js +2 -1
  106. package/dist/utils/setupFiles.d.ts +2 -1
  107. package/dist/utils/setupFiles.js +723 -28
  108. package/dist/utils/validationRules.d.ts +43 -0
  109. package/dist/utils/validationRules.js +42 -0
  110. package/dist/utils/yamlConverter.d.ts +48 -0
  111. package/dist/utils/yamlConverter.js +98 -0
  112. package/dist/utilsController.js +65 -43
  113. package/package.json +19 -15
  114. package/src/collections/attributes.ts +3 -2
  115. package/src/collections/methods.ts +85 -51
  116. package/src/config/yamlConfig.ts +488 -0
  117. package/src/{migrations/setupDatabase.ts → databases/setup.ts} +11 -5
  118. package/src/functions/methods.ts +8 -4
  119. package/src/functions/templates/count-docs-in-collection/package.json +25 -0
  120. package/src/functions/templates/count-docs-in-collection/tsconfig.json +28 -0
  121. package/src/functions/templates/typescript-node/package.json +24 -0
  122. package/src/functions/templates/typescript-node/tsconfig.json +28 -0
  123. package/src/functions/templates/uv/README.md +31 -0
  124. package/src/functions/templates/uv/pyproject.toml +29 -0
  125. package/src/interactiveCLI.ts +226 -61
  126. package/src/main.ts +111 -37
  127. package/src/migrations/afterImportActions.ts +2 -2
  128. package/src/migrations/appwriteToX.ts +17 -4
  129. package/src/migrations/dataLoader.ts +4 -4
  130. package/src/migrations/importController.ts +30 -22
  131. package/src/migrations/importDataActions.ts +2 -2
  132. package/src/migrations/relationships.ts +1 -1
  133. package/src/migrations/services/DataTransformationService.ts +196 -0
  134. package/src/migrations/services/FileHandlerService.ts +311 -0
  135. package/src/migrations/services/ImportOrchestrator.ts +669 -0
  136. package/src/migrations/services/RateLimitManager.ts +363 -0
  137. package/src/migrations/services/RelationshipResolver.ts +461 -0
  138. package/src/migrations/services/UserMappingService.ts +345 -0
  139. package/src/migrations/services/ValidationService.ts +349 -0
  140. package/src/migrations/transfer.ts +22 -228
  141. package/src/migrations/yaml/YamlImportConfigLoader.ts +427 -0
  142. package/src/migrations/yaml/YamlImportIntegration.ts +419 -0
  143. package/src/migrations/yaml/generateImportSchemas.ts +589 -0
  144. package/src/shared/attributeManager.ts +429 -0
  145. package/src/shared/confirmationDialogs.ts +327 -0
  146. package/src/shared/functionManager.ts +515 -0
  147. package/src/shared/indexManager.ts +253 -0
  148. package/src/shared/jsonSchemaGenerator.ts +403 -0
  149. package/src/shared/logging.ts +74 -0
  150. package/src/shared/messageFormatter.ts +195 -0
  151. package/src/{migrations/migrationHelper.ts → shared/migrationHelpers.ts} +22 -4
  152. package/src/{migrations/helper.ts → shared/operationLogger.ts} +7 -2
  153. package/src/{migrations/queue.ts → shared/operationQueue.ts} +1 -1
  154. package/src/shared/progressManager.ts +278 -0
  155. package/src/{migrations/schemaStrings.ts → shared/schemaGenerator.ts} +71 -17
  156. package/src/storage/methods.ts +199 -78
  157. package/src/types.ts +2 -2
  158. package/src/{migrations/users.ts → users/methods.ts} +2 -2
  159. package/src/utils/configMigration.ts +349 -0
  160. package/src/utils/loadConfigs.ts +416 -52
  161. package/src/utils/schemaStrings.ts +2 -1
  162. package/src/utils/setupFiles.ts +742 -40
  163. package/src/{migrations → utils}/validationRules.ts +1 -1
  164. package/src/utils/yamlConverter.ts +131 -0
  165. package/src/utilsController.ts +75 -54
  166. package/src/functions/templates/poetry/README.md +0 -30
  167. package/src/functions/templates/poetry/pyproject.toml +0 -16
  168. package/src/migrations/attributes.ts +0 -561
  169. package/src/migrations/backup.ts +0 -205
  170. package/src/migrations/databases.ts +0 -39
  171. package/src/migrations/dbHelpers.ts +0 -92
  172. package/src/migrations/indexes.ts +0 -40
  173. package/src/migrations/logging.ts +0 -29
  174. package/src/migrations/storage.ts +0 -538
  175. /package/src/{migrations → functions}/openapi.ts +0 -0
  176. /package/src/functions/templates/{poetry → uv}/src/__init__.py +0 -0
  177. /package/src/functions/templates/{poetry → uv}/src/index.py +0 -0
  178. /package/src/{migrations/converters.ts → utils/dataConverters.ts} +0 -0
package/dist/main.js CHANGED
@@ -6,29 +6,31 @@ import { InteractiveCLI } from "./interactiveCLI.js";
6
6
  import { UtilsController } from "./utilsController.js";
7
7
  import { Databases, Storage } from "node-appwrite";
8
8
  import { getClient } from "./utils/getClientFromConfig.js";
9
- import { fetchAllDatabases } from "./migrations/databases.js";
9
+ import { fetchAllDatabases } from "./databases/methods.js";
10
10
  import { setupDirsFiles } from "./utils/setupFiles.js";
11
11
  import { fetchAllCollections } from "./collections/methods.js";
12
12
  import chalk from "chalk";
13
13
  import { listSpecifications } from "./functions/methods.js";
14
+ import { MessageFormatter } from "./shared/messageFormatter.js";
15
+ import { ConfirmationDialogs } from "./shared/confirmationDialogs.js";
14
16
  const argv = yargs(hideBin(process.argv))
15
17
  .option("config", {
16
18
  type: "string",
17
- description: "Appwrite Config file name",
19
+ description: "Path to Appwrite configuration file (appwriteConfig.ts)",
18
20
  })
19
21
  .option("it", {
20
22
  alias: ["interactive", "i"],
21
23
  type: "boolean",
22
- description: "Run in interactive mode",
24
+ description: "Launch interactive CLI mode with guided prompts",
23
25
  })
24
26
  .option("dbIds", {
25
27
  type: "string",
26
- description: "Comma-separated list of database IDs to operate on",
28
+ description: "Comma-separated list of database IDs to target (e.g., 'db1,db2,db3')",
27
29
  })
28
30
  .option("collectionIds", {
29
31
  alias: ["collIds"],
30
32
  type: "string",
31
- description: "Comma-separated list of collection IDs to operate on",
33
+ description: "Comma-separated list of collection IDs to target (e.g., 'users,posts')",
32
34
  })
33
35
  .option("bucketIds", {
34
36
  type: "string",
@@ -36,11 +38,11 @@ const argv = yargs(hideBin(process.argv))
36
38
  })
37
39
  .option("wipe", {
38
40
  choices: ["all", "docs", "users"],
39
- description: "Wipe data (all: everything, docs: only documents, users: only user data)",
41
+ description: "⚠️ DESTRUCTIVE: Wipe data (all: databases+storage+users, docs: documents only, users: user accounts only)",
40
42
  })
41
43
  .option("wipeCollections", {
42
44
  type: "boolean",
43
- description: "Wipe collections, uses collectionIds option to get the collections to wipe",
45
+ description: "⚠️ DESTRUCTIVE: Wipe specific collections (requires --collectionIds)",
44
46
  })
45
47
  .option("transferUsers", {
46
48
  type: "boolean",
@@ -48,27 +50,27 @@ const argv = yargs(hideBin(process.argv))
48
50
  })
49
51
  .option("generate", {
50
52
  type: "boolean",
51
- description: "Generate TypeScript schemas from database schemas",
53
+ description: "Generate TypeScript schemas and types from your Appwrite database schemas",
52
54
  })
53
55
  .option("import", {
54
56
  type: "boolean",
55
- description: "Import data into your databases",
57
+ description: "Import data from importData/ directory into your Appwrite databases",
56
58
  })
57
59
  .option("backup", {
58
60
  type: "boolean",
59
- description: "Perform a backup of your databases",
61
+ description: "Create a complete backup of your databases and collections",
60
62
  })
61
63
  .option("writeData", {
62
64
  type: "boolean",
63
- description: "Write converted imported data to file",
65
+ description: "Output converted import data to files for validation before importing",
64
66
  })
65
67
  .option("push", {
66
68
  type: "boolean",
67
- description: "Push your local Appwrite config to your configured Appwrite Project",
69
+ description: "Deploy your local configuration (collections, attributes, indexes) to Appwrite",
68
70
  })
69
71
  .option("sync", {
70
72
  type: "boolean",
71
- description: "Synchronize by pulling your Appwrite config from your configured Appwrite Project",
73
+ description: "Pull and synchronize your local config with the remote Appwrite project schema",
72
74
  })
73
75
  .option("endpoint", {
74
76
  type: "string",
@@ -84,17 +86,17 @@ const argv = yargs(hideBin(process.argv))
84
86
  })
85
87
  .option("transfer", {
86
88
  type: "boolean",
87
- description: "Transfer data between databases or collections",
89
+ description: "Transfer documents and files between databases, collections, or projects",
88
90
  })
89
91
  .option("fromDbId", {
90
92
  alias: ["fromDb", "sourceDbId", "sourceDb"],
91
93
  type: "string",
92
- description: "Set the source database ID for transfer",
94
+ description: "Source database ID for transfer operations",
93
95
  })
94
96
  .option("toDbId", {
95
97
  alias: ["toDb", "targetDbId", "targetDb"],
96
98
  type: "string",
97
- description: "Set the destination database ID for transfer",
99
+ description: "Target database ID for transfer operations",
98
100
  })
99
101
  .option("fromCollectionId", {
100
102
  alias: ["fromCollId", "fromColl"],
@@ -128,7 +130,7 @@ const argv = yargs(hideBin(process.argv))
128
130
  })
129
131
  .option("setup", {
130
132
  type: "boolean",
131
- description: "Setup directories and files",
133
+ description: "Initialize project with configuration files and directory structure",
132
134
  })
133
135
  .option("updateFunctionSpec", {
134
136
  type: "boolean",
@@ -151,9 +153,16 @@ const argv = yargs(hideBin(process.argv))
151
153
  "s-8vcpu-4gb",
152
154
  "s-8vcpu-8gb",
153
155
  ],
156
+ })
157
+ .option("migrateConfig", {
158
+ alias: ["migrate"],
159
+ type: "boolean",
160
+ description: "Migrate appwriteConfig.ts to .appwrite structure with YAML configuration",
154
161
  })
155
162
  .parse();
156
163
  async function main() {
164
+ const startTime = Date.now();
165
+ const operationStats = {};
157
166
  if (argv.it) {
158
167
  const cli = new InteractiveCLI(process.cwd());
159
168
  await cli.run();
@@ -172,8 +181,13 @@ async function main() {
172
181
  await setupDirsFiles(false, process.cwd());
173
182
  return;
174
183
  }
184
+ if (argv.migrateConfig) {
185
+ const { migrateConfig } = await import("./utils/configMigration.js");
186
+ await migrateConfig(process.cwd());
187
+ return;
188
+ }
175
189
  if (!controller.config) {
176
- console.log(chalk.red("No Appwrite connection found"));
190
+ MessageFormatter.error("No Appwrite connection found", undefined, { prefix: "CLI" });
177
191
  return;
178
192
  }
179
193
  const parsedArgv = argv;
@@ -196,10 +210,10 @@ async function main() {
196
210
  if (!parsedArgv.functionId || !parsedArgv.specification) {
197
211
  throw new Error("Function ID and specification are required for updating function specs");
198
212
  }
199
- console.log(chalk.yellow(`Updating function specification for ${parsedArgv.functionId} to ${parsedArgv.specification}, checking if specification exists...`));
213
+ MessageFormatter.info(`Updating function specification for ${parsedArgv.functionId} to ${parsedArgv.specification}`, { prefix: "Functions" });
200
214
  const specifications = await listSpecifications(controller.appwriteServer);
201
215
  if (!specifications.specifications.some((s) => s.slug === parsedArgv.specification)) {
202
- console.log(chalk.red(`Specification ${parsedArgv.specification} not found`));
216
+ MessageFormatter.error(`Specification ${parsedArgv.specification} not found`, undefined, { prefix: "Functions" });
203
217
  return;
204
218
  }
205
219
  await controller.updateFunctionSpecifications(parsedArgv.functionId, parsedArgv.specification);
@@ -207,7 +221,10 @@ async function main() {
207
221
  // Add default databases if not specified
208
222
  if (!options.databases || options.databases.length === 0) {
209
223
  const allDatabases = await fetchAllDatabases(controller.database);
210
- options.databases = allDatabases.filter((db) => db.name.toLowerCase() !== "migrations");
224
+ options.databases = allDatabases.filter((db) => {
225
+ const useMigrations = controller.config?.useMigrations ?? true;
226
+ return useMigrations || db.name.toLowerCase() !== "migrations";
227
+ });
211
228
  }
212
229
  // Add default collections if not specified
213
230
  if (!options.collections || options.collections.length === 0) {
@@ -219,47 +236,80 @@ async function main() {
219
236
  }
220
237
  }
221
238
  if (options.doBackup && options.databases) {
239
+ MessageFormatter.info(`Creating backups for ${options.databases.length} database(s)`, { prefix: "Backup" });
222
240
  for (const db of options.databases) {
223
241
  await controller.backupDatabase(db);
224
242
  }
243
+ operationStats.backups = options.databases.length;
244
+ MessageFormatter.success(`Backup completed for ${options.databases.length} database(s)`, { prefix: "Backup" });
225
245
  }
226
246
  if (options.wipeDatabase ||
227
247
  options.wipeDocumentStorage ||
228
248
  options.wipeUsers ||
229
249
  options.wipeCollections) {
250
+ // Confirm destructive operations
251
+ const databaseNames = options.databases?.map(db => db.name) || [];
252
+ const confirmed = await ConfirmationDialogs.confirmDatabaseWipe(databaseNames, {
253
+ includeStorage: options.wipeDocumentStorage,
254
+ includeUsers: options.wipeUsers
255
+ });
256
+ if (!confirmed) {
257
+ MessageFormatter.info("Operation cancelled by user", { prefix: "CLI" });
258
+ return;
259
+ }
260
+ let wipeStats = { databases: 0, collections: 0, users: 0, buckets: 0 };
230
261
  if (parsedArgv.wipe === "all") {
231
262
  if (options.databases) {
232
263
  for (const db of options.databases) {
233
264
  await controller.wipeDatabase(db, true); // true to wipe associated buckets
234
265
  }
266
+ wipeStats.databases = options.databases.length;
235
267
  }
236
268
  await controller.wipeUsers();
269
+ wipeStats.users = 1;
237
270
  }
238
271
  else if (parsedArgv.wipe === "docs") {
239
272
  if (options.databases) {
240
273
  for (const db of options.databases) {
241
274
  await controller.wipeBucketFromDatabase(db);
242
275
  }
276
+ wipeStats.databases = options.databases.length;
243
277
  }
244
278
  if (parsedArgv.bucketIds) {
245
- for (const bucketId of parsedArgv.bucketIds.split(",")) {
279
+ const bucketIds = parsedArgv.bucketIds.split(",");
280
+ for (const bucketId of bucketIds) {
246
281
  await controller.wipeDocumentStorage(bucketId);
247
282
  }
283
+ wipeStats.buckets = bucketIds.length;
248
284
  }
249
285
  }
250
286
  else if (parsedArgv.wipe === "users") {
251
287
  await controller.wipeUsers();
288
+ wipeStats.users = 1;
252
289
  }
253
290
  // Handle specific collection wipes
254
291
  if (options.wipeCollections && options.databases) {
255
292
  for (const db of options.databases) {
256
293
  const dbCollections = await fetchAllCollections(db.$id, controller.database);
257
294
  const collectionsToWipe = dbCollections.filter((c) => options.collections.includes(c.$id));
258
- for (const collection of collectionsToWipe) {
259
- await controller.wipeCollection(db, collection);
295
+ // Confirm collection wipe
296
+ const collectionNames = collectionsToWipe.map(c => c.name);
297
+ const collectionConfirmed = await ConfirmationDialogs.confirmCollectionWipe(db.name, collectionNames);
298
+ if (collectionConfirmed) {
299
+ for (const collection of collectionsToWipe) {
300
+ await controller.wipeCollection(db, collection);
301
+ }
302
+ wipeStats.collections += collectionsToWipe.length;
260
303
  }
261
304
  }
262
305
  }
306
+ // Show wipe operation summary
307
+ if (wipeStats.databases > 0 || wipeStats.collections > 0 || wipeStats.users > 0 || wipeStats.buckets > 0) {
308
+ operationStats.wipedDatabases = wipeStats.databases;
309
+ operationStats.wipedCollections = wipeStats.collections;
310
+ operationStats.wipedUsers = wipeStats.users;
311
+ operationStats.wipedBuckets = wipeStats.buckets;
312
+ }
263
313
  }
264
314
  if (parsedArgv.push || parsedArgv.sync) {
265
315
  const databases = options.databases || (await fetchAllDatabases(controller.database));
@@ -272,16 +322,21 @@ async function main() {
272
322
  }
273
323
  if (parsedArgv.push) {
274
324
  await controller.syncDb(databases, collections);
325
+ operationStats.pushedDatabases = databases.length;
326
+ operationStats.pushedCollections = collections.length;
275
327
  }
276
328
  else if (parsedArgv.sync) {
277
329
  await controller.synchronizeConfigurations(databases);
330
+ operationStats.syncedDatabases = databases.length;
278
331
  }
279
332
  }
280
333
  if (options.generateSchemas) {
281
334
  await controller.generateSchemas();
335
+ operationStats.generatedSchemas = 1;
282
336
  }
283
337
  if (options.importData) {
284
338
  await controller.importData(options);
339
+ operationStats.importCompleted = 1;
285
340
  }
286
341
  if (parsedArgv.transfer) {
287
342
  const isRemote = !!parsedArgv.remoteEndpoint;
@@ -290,10 +345,10 @@ async function main() {
290
345
  let targetStorage;
291
346
  // Only fetch databases if database IDs are provided
292
347
  if (parsedArgv.fromDbId && parsedArgv.toDbId) {
293
- console.log(chalk.blue(`Starting database transfer from ${parsedArgv.fromDbId} to ${parsedArgv.toDbId}`));
348
+ MessageFormatter.info(`Starting database transfer from ${parsedArgv.fromDbId} to ${parsedArgv.toDbId}`, { prefix: "Transfer" });
294
349
  fromDb = (await controller.getDatabasesByIds([parsedArgv.fromDbId]))?.[0];
295
350
  if (!fromDb) {
296
- console.log(chalk.red("Source database not found"));
351
+ MessageFormatter.error("Source database not found", undefined, { prefix: "Transfer" });
297
352
  return;
298
353
  }
299
354
  if (isRemote) {
@@ -308,19 +363,19 @@ async function main() {
308
363
  const remoteDbs = await fetchAllDatabases(targetDatabases);
309
364
  toDb = remoteDbs.find((db) => db.$id === parsedArgv.toDbId);
310
365
  if (!toDb) {
311
- console.log(chalk.red("Target database not found"));
366
+ MessageFormatter.error("Target database not found", undefined, { prefix: "Transfer" });
312
367
  return;
313
368
  }
314
369
  }
315
370
  else {
316
371
  toDb = (await controller.getDatabasesByIds([parsedArgv.toDbId]))?.[0];
317
372
  if (!toDb) {
318
- console.log(chalk.red("Target database not found"));
373
+ MessageFormatter.error("Target database not found", undefined, { prefix: "Transfer" });
319
374
  return;
320
375
  }
321
376
  }
322
377
  if (!fromDb || !toDb) {
323
- console.log(chalk.red("Source or target database not found"));
378
+ MessageFormatter.error("Source or target database not found", undefined, { prefix: "Transfer" });
324
379
  return;
325
380
  }
326
381
  }
@@ -357,10 +412,16 @@ async function main() {
357
412
  transferUsers: options.transferUsers,
358
413
  };
359
414
  await controller.transferData(transferOptions);
415
+ operationStats.transfers = 1;
416
+ }
417
+ // Show final operation summary if any operations were performed
418
+ if (Object.keys(operationStats).length > 0) {
419
+ const duration = Date.now() - startTime;
420
+ MessageFormatter.operationSummary("CLI Operations", operationStats, duration);
360
421
  }
361
422
  }
362
423
  }
363
424
  main().catch((error) => {
364
- console.error("An error occurred:", error);
425
+ MessageFormatter.error("CLI execution failed", error, { prefix: "CLI" });
365
426
  process.exit(1);
366
427
  });
@@ -3,7 +3,7 @@ import { InputFile } from "node-appwrite/file";
3
3
  import path from "path";
4
4
  import fs from "fs";
5
5
  import os from "os";
6
- import { logger } from "./logging.js";
6
+ import { logger } from "../shared/logging.js";
7
7
  import { tryAwaitWithRetry, } from "appwrite-utils";
8
8
  export const getDatabaseFromConfig = (config) => {
9
9
  if (!config.appwriteClient) {
@@ -264,7 +264,7 @@ export const afterImportActions = {
264
264
  // Use arrayBuffer if buffer is not available
265
265
  const arrayBuffer = await response.arrayBuffer();
266
266
  const buffer = Buffer.from(arrayBuffer);
267
- fs.writeFileSync(tempFilePath, buffer);
267
+ fs.writeFileSync(tempFilePath, new Uint8Array(buffer));
268
268
  // Create InputFile from the downloaded file
269
269
  const inputFile = InputFile.fromPath(tempFilePath, fileName);
270
270
  // Use the full file name (with extension) for creating the file
@@ -25,6 +25,16 @@ export declare class AppwriteToX {
25
25
  xdefault?: number | null | undefined;
26
26
  min?: number | undefined;
27
27
  max?: number | undefined;
28
+ } | {
29
+ type: "double";
30
+ key: string;
31
+ description?: string | Record<string, string> | null | undefined;
32
+ required?: boolean | undefined;
33
+ array?: boolean | undefined;
34
+ error?: string | undefined;
35
+ xdefault?: number | null | undefined;
36
+ min?: number | undefined;
37
+ max?: number | undefined;
28
38
  } | {
29
39
  type: "float";
30
40
  key: string;
@@ -1,7 +1,8 @@
1
- import { SchemaGenerator } from "./schemaStrings.js";
1
+ import { SchemaGenerator } from "../shared/schemaGenerator.js";
2
+ import { findYamlConfig } from "../config/yamlConfig.js";
2
3
  import { Client, Compression, Databases, Query, Storage, } from "node-appwrite";
3
4
  import { fetchAllCollections } from "../collections/methods.js";
4
- import { fetchAllDatabases } from "./databases.js";
5
+ import { fetchAllDatabases } from "../databases/methods.js";
5
6
  import { CollectionSchema, attributeSchema, AppwriteConfigSchema, permissionsSchema, attributesSchema, indexesSchema, parseAttribute, } from "appwrite-utils";
6
7
  import { getDatabaseFromConfig } from "./afterImportActions.js";
7
8
  import { listBuckets } from "../storage/methods.js";
@@ -57,7 +58,7 @@ export class AppwriteToX {
57
58
  const allBuckets = await listBuckets(this.storage);
58
59
  // Loop through each database
59
60
  for (const database of databases) {
60
- if (database.name.toLowerCase() === "migrations") {
61
+ if (!this.config.useMigrations && database.name.toLowerCase() === "migrations") {
61
62
  continue;
62
63
  }
63
64
  // Match bucket to database
@@ -189,7 +190,17 @@ export class AppwriteToX {
189
190
  async toSchemas(databases) {
190
191
  await this.appwriteSync(this.config, databases);
191
192
  const generator = new SchemaGenerator(this.updatedConfig, this.appwriteFolderPath);
192
- generator.updateTsSchemas();
193
+ // Check if this is a YAML-based project
194
+ const yamlConfigPath = findYamlConfig(this.appwriteFolderPath);
195
+ const isYamlProject = !!yamlConfigPath;
196
+ if (isYamlProject) {
197
+ console.log("📄 Detected YAML configuration - generating YAML collection definitions");
198
+ generator.updateYamlCollections();
199
+ }
200
+ else {
201
+ console.log("📝 Generating TypeScript collection definitions");
202
+ generator.updateTsSchemas();
203
+ }
193
204
  generator.generateSchemas();
194
205
  }
195
206
  }
@@ -9,31 +9,31 @@ export declare const BackupSchema: z.ZodObject<{
9
9
  collectionId: z.ZodString;
10
10
  data: z.ZodString;
11
11
  }, "strip", z.ZodTypeAny, {
12
- collectionId: string;
13
12
  data: string;
14
- }, {
15
13
  collectionId: string;
14
+ }, {
16
15
  data: string;
16
+ collectionId: string;
17
17
  }>, "many">>;
18
18
  }, "strip", z.ZodTypeAny, {
19
- collections: string[];
20
19
  documents: {
21
- collectionId: string;
22
20
  data: string;
21
+ collectionId: string;
23
22
  }[];
24
23
  $id: string;
24
+ collections: string[];
25
25
  $createdAt: string;
26
26
  $updatedAt: string;
27
27
  database: string;
28
28
  }, {
29
- collections: string[];
30
29
  $id: string;
30
+ collections: string[];
31
31
  $createdAt: string;
32
32
  $updatedAt: string;
33
33
  database: string;
34
34
  documents?: {
35
- collectionId: string;
36
35
  data: string;
36
+ collectionId: string;
37
37
  }[] | undefined;
38
38
  }>;
39
39
  export type Backup = z.infer<typeof BackupSchema>;
@@ -47,25 +47,25 @@ export declare const BackupCreateSchema: z.ZodObject<Omit<{
47
47
  collectionId: z.ZodString;
48
48
  data: z.ZodString;
49
49
  }, "strip", z.ZodTypeAny, {
50
- collectionId: string;
51
50
  data: string;
52
- }, {
53
51
  collectionId: string;
52
+ }, {
54
53
  data: string;
54
+ collectionId: string;
55
55
  }>, "many">>;
56
56
  }, "$id" | "$createdAt" | "$updatedAt">, "strip", z.ZodTypeAny, {
57
- collections: string[];
58
57
  documents: {
59
- collectionId: string;
60
58
  data: string;
59
+ collectionId: string;
61
60
  }[];
61
+ collections: string[];
62
62
  database: string;
63
63
  }, {
64
64
  collections: string[];
65
65
  database: string;
66
66
  documents?: {
67
- collectionId: string;
68
67
  data: string;
68
+ collectionId: string;
69
69
  }[] | undefined;
70
70
  }>;
71
71
  export type BackupCreate = z.infer<typeof BackupCreateSchema>;
@@ -76,16 +76,16 @@ export declare const BatchSchema: z.ZodObject<{
76
76
  data: z.ZodString;
77
77
  processed: z.ZodDefault<z.ZodBoolean>;
78
78
  }, "strip", z.ZodTypeAny, {
79
+ data: string;
79
80
  $id: string;
80
81
  $createdAt: string;
81
82
  $updatedAt: string;
82
- data: string;
83
83
  processed: boolean;
84
84
  }, {
85
+ data: string;
85
86
  $id: string;
86
87
  $createdAt: string;
87
88
  $updatedAt: string;
88
- data: string;
89
89
  processed?: boolean | undefined;
90
90
  }>;
91
91
  export type Batch = z.infer<typeof BatchSchema>;
@@ -116,11 +116,11 @@ export declare const OperationSchema: z.ZodObject<{
116
116
  error: z.ZodString;
117
117
  status: z.ZodDefault<z.ZodEnum<["pending", "ready", "in_progress", "completed", "error", "cancelled"]>>;
118
118
  }, "strip", z.ZodTypeAny, {
119
+ status: "error" | "pending" | "ready" | "in_progress" | "completed" | "cancelled";
120
+ error: string;
119
121
  $id: string;
120
122
  $createdAt: string;
121
123
  $updatedAt: string;
122
- status: "error" | "pending" | "ready" | "in_progress" | "completed" | "cancelled";
123
- error: string;
124
124
  collectionId: string;
125
125
  operationType: string;
126
126
  progress: number;
@@ -128,10 +128,10 @@ export declare const OperationSchema: z.ZodObject<{
128
128
  data?: any;
129
129
  batches?: string[] | undefined;
130
130
  }, {
131
+ error: string;
131
132
  $id: string;
132
133
  $createdAt: string;
133
134
  $updatedAt: string;
134
- error: string;
135
135
  collectionId: string;
136
136
  operationType: string;
137
137
  progress: number;
@@ -87,7 +87,6 @@ export declare const CollectionImportDataSchema: z.ZodObject<{
87
87
  max?: number | undefined;
88
88
  }>, z.ZodObject<{
89
89
  key: z.ZodString;
90
- type: z.ZodDefault<z.ZodLiteral<"float">>;
91
90
  error: z.ZodOptional<z.ZodDefault<z.ZodString>>;
92
91
  required: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
93
92
  array: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
@@ -95,6 +94,39 @@ export declare const CollectionImportDataSchema: z.ZodObject<{
95
94
  max: z.ZodOptional<z.ZodNumber>;
96
95
  xdefault: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
97
96
  description: z.ZodOptional<z.ZodNullable<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>>;
97
+ } & {
98
+ type: z.ZodDefault<z.ZodLiteral<"double">>;
99
+ }, "strip", z.ZodTypeAny, {
100
+ type: "double";
101
+ key: string;
102
+ description?: string | Record<string, string> | null | undefined;
103
+ required?: boolean | undefined;
104
+ array?: boolean | undefined;
105
+ error?: string | undefined;
106
+ xdefault?: number | null | undefined;
107
+ min?: number | undefined;
108
+ max?: number | undefined;
109
+ }, {
110
+ key: string;
111
+ type?: "double" | undefined;
112
+ description?: string | Record<string, string> | null | undefined;
113
+ required?: boolean | undefined;
114
+ array?: boolean | undefined;
115
+ error?: string | undefined;
116
+ xdefault?: number | null | undefined;
117
+ min?: number | undefined;
118
+ max?: number | undefined;
119
+ }>, z.ZodObject<{
120
+ key: z.ZodString;
121
+ error: z.ZodOptional<z.ZodDefault<z.ZodString>>;
122
+ required: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
123
+ array: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
124
+ min: z.ZodOptional<z.ZodNumber>;
125
+ max: z.ZodOptional<z.ZodNumber>;
126
+ xdefault: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
127
+ description: z.ZodOptional<z.ZodNullable<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>>;
128
+ } & {
129
+ type: z.ZodDefault<z.ZodLiteral<"float">>;
98
130
  }, "strip", z.ZodTypeAny, {
99
131
  type: "float";
100
132
  key: string;
@@ -561,6 +593,16 @@ export declare const CollectionImportDataSchema: z.ZodObject<{
561
593
  xdefault?: number | null | undefined;
562
594
  min?: number | undefined;
563
595
  max?: number | undefined;
596
+ } | {
597
+ type: "double";
598
+ key: string;
599
+ description?: string | Record<string, string> | null | undefined;
600
+ required?: boolean | undefined;
601
+ array?: boolean | undefined;
602
+ error?: string | undefined;
603
+ xdefault?: number | null | undefined;
604
+ min?: number | undefined;
605
+ max?: number | undefined;
564
606
  } | {
565
607
  type: "float";
566
608
  key: string;
@@ -716,6 +758,16 @@ export declare const CollectionImportDataSchema: z.ZodObject<{
716
758
  xdefault?: number | null | undefined;
717
759
  min?: number | undefined;
718
760
  max?: number | undefined;
761
+ } | {
762
+ key: string;
763
+ type?: "double" | undefined;
764
+ description?: string | Record<string, string> | null | undefined;
765
+ required?: boolean | undefined;
766
+ array?: boolean | undefined;
767
+ error?: string | undefined;
768
+ xdefault?: number | null | undefined;
769
+ min?: number | undefined;
770
+ max?: number | undefined;
719
771
  } | {
720
772
  key: string;
721
773
  type?: "float" | undefined;
@@ -1181,6 +1233,16 @@ export declare const CollectionImportDataSchema: z.ZodObject<{
1181
1233
  xdefault?: number | null | undefined;
1182
1234
  min?: number | undefined;
1183
1235
  max?: number | undefined;
1236
+ } | {
1237
+ type: "double";
1238
+ key: string;
1239
+ description?: string | Record<string, string> | null | undefined;
1240
+ required?: boolean | undefined;
1241
+ array?: boolean | undefined;
1242
+ error?: string | undefined;
1243
+ xdefault?: number | null | undefined;
1244
+ min?: number | undefined;
1245
+ max?: number | undefined;
1184
1246
  } | {
1185
1247
  type: "float";
1186
1248
  key: string;
@@ -1380,6 +1442,16 @@ export declare const CollectionImportDataSchema: z.ZodObject<{
1380
1442
  xdefault?: number | null | undefined;
1381
1443
  min?: number | undefined;
1382
1444
  max?: number | undefined;
1445
+ } | {
1446
+ key: string;
1447
+ type?: "double" | undefined;
1448
+ description?: string | Record<string, string> | null | undefined;
1449
+ required?: boolean | undefined;
1450
+ array?: boolean | undefined;
1451
+ error?: string | undefined;
1452
+ xdefault?: number | null | undefined;
1453
+ min?: number | undefined;
1454
+ max?: number | undefined;
1383
1455
  } | {
1384
1456
  key: string;
1385
1457
  type?: "float" | undefined;
@@ -1585,6 +1657,16 @@ export declare class DataLoader {
1585
1657
  xdefault?: number | null | undefined;
1586
1658
  min?: number | undefined;
1587
1659
  max?: number | undefined;
1660
+ } | {
1661
+ type: "double";
1662
+ key: string;
1663
+ description?: string | Record<string, string> | null | undefined;
1664
+ required?: boolean | undefined;
1665
+ array?: boolean | undefined;
1666
+ error?: string | undefined;
1667
+ xdefault?: number | null | undefined;
1668
+ min?: number | undefined;
1669
+ max?: number | undefined;
1588
1670
  } | {
1589
1671
  type: "float";
1590
1672
  key: string;
@@ -1,14 +1,14 @@
1
1
  import { AttributeMappingsSchema, CollectionCreateSchema, importDefSchema, } from "appwrite-utils";
2
2
  import path from "path";
3
3
  import fs from "fs";
4
- import { convertObjectByAttributeMappings } from "./converters.js";
4
+ import { convertObjectByAttributeMappings } from "../utils/dataConverters.js";
5
5
  import { z } from "zod";
6
6
  import { checkForCollection } from "../collections/methods.js";
7
7
  import { ID, Users } from "node-appwrite";
8
- import { logger } from "./logging.js";
9
- import { findOrCreateOperation, updateOperation } from "./migrationHelper.js";
8
+ import { logger } from "../shared/logging.js";
9
+ import { findOrCreateOperation, updateOperation } from "../shared/migrationHelpers.js";
10
10
  import { AuthUserCreateSchema } from "../schemas/authUser.js";
11
- import { UsersController } from "./users.js";
11
+ import { UsersController } from "../users/methods.js";
12
12
  import { finalizeByAttributeMap } from "../utils/helperFunctions.js";
13
13
  import { isEmpty } from "es-toolkit/compat";
14
14
  // Define a schema for the structure of collection import data using Zod for validation