appwrite-utils-cli 0.10.86 → 1.0.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 (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 +260 -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 +156 -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 +377 -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 +212 -0
  160. package/src/utils/loadConfigs.ts +414 -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/src/main.ts CHANGED
@@ -7,12 +7,14 @@ import { UtilsController, type SetupOptions } from "./utilsController.js";
7
7
  import type { TransferOptions } from "./migrations/transfer.js";
8
8
  import { Databases, Storage, type Models } from "node-appwrite";
9
9
  import { getClient } from "./utils/getClientFromConfig.js";
10
- import { fetchAllDatabases } from "./migrations/databases.js";
10
+ import { fetchAllDatabases } from "./databases/methods.js";
11
11
  import { setupDirsFiles } from "./utils/setupFiles.js";
12
12
  import { fetchAllCollections } from "./collections/methods.js";
13
13
  import type { Specification } from "appwrite-utils";
14
14
  import chalk from "chalk";
15
15
  import { listSpecifications } from "./functions/methods.js";
16
+ import { MessageFormatter } from "./shared/messageFormatter.js";
17
+ import { ConfirmationDialogs } from "./shared/confirmationDialogs.js";
16
18
 
17
19
  interface CliOptions {
18
20
  config?: string;
@@ -46,6 +48,7 @@ interface CliOptions {
46
48
  updateFunctionSpec?: boolean;
47
49
  functionId?: string;
48
50
  specification?: string;
51
+ migrateConfig?: boolean;
49
52
  }
50
53
 
51
54
  type ParsedArgv = ArgumentsCamelCase<CliOptions>;
@@ -53,21 +56,21 @@ type ParsedArgv = ArgumentsCamelCase<CliOptions>;
53
56
  const argv = yargs(hideBin(process.argv))
54
57
  .option("config", {
55
58
  type: "string",
56
- description: "Appwrite Config file name",
59
+ description: "Path to Appwrite configuration file (appwriteConfig.ts)",
57
60
  })
58
61
  .option("it", {
59
62
  alias: ["interactive", "i"],
60
63
  type: "boolean",
61
- description: "Run in interactive mode",
64
+ description: "Launch interactive CLI mode with guided prompts",
62
65
  })
63
66
  .option("dbIds", {
64
67
  type: "string",
65
- description: "Comma-separated list of database IDs to operate on",
68
+ description: "Comma-separated list of database IDs to target (e.g., 'db1,db2,db3')",
66
69
  })
67
70
  .option("collectionIds", {
68
71
  alias: ["collIds"],
69
72
  type: "string",
70
- description: "Comma-separated list of collection IDs to operate on",
73
+ description: "Comma-separated list of collection IDs to target (e.g., 'users,posts')",
71
74
  })
72
75
  .option("bucketIds", {
73
76
  type: "string",
@@ -76,12 +79,12 @@ const argv = yargs(hideBin(process.argv))
76
79
  .option("wipe", {
77
80
  choices: ["all", "docs", "users"] as const,
78
81
  description:
79
- "Wipe data (all: everything, docs: only documents, users: only user data)",
82
+ "⚠️ DESTRUCTIVE: Wipe data (all: databases+storage+users, docs: documents only, users: user accounts only)",
80
83
  })
81
84
  .option("wipeCollections", {
82
85
  type: "boolean",
83
86
  description:
84
- "Wipe collections, uses collectionIds option to get the collections to wipe",
87
+ "⚠️ DESTRUCTIVE: Wipe specific collections (requires --collectionIds)",
85
88
  })
86
89
  .option("transferUsers", {
87
90
  type: "boolean",
@@ -89,29 +92,29 @@ const argv = yargs(hideBin(process.argv))
89
92
  })
90
93
  .option("generate", {
91
94
  type: "boolean",
92
- description: "Generate TypeScript schemas from database schemas",
95
+ description: "Generate TypeScript schemas and types from your Appwrite database schemas",
93
96
  })
94
97
  .option("import", {
95
98
  type: "boolean",
96
- description: "Import data into your databases",
99
+ description: "Import data from importData/ directory into your Appwrite databases",
97
100
  })
98
101
  .option("backup", {
99
102
  type: "boolean",
100
- description: "Perform a backup of your databases",
103
+ description: "Create a complete backup of your databases and collections",
101
104
  })
102
105
  .option("writeData", {
103
106
  type: "boolean",
104
- description: "Write converted imported data to file",
107
+ description: "Output converted import data to files for validation before importing",
105
108
  })
106
109
  .option("push", {
107
110
  type: "boolean",
108
111
  description:
109
- "Push your local Appwrite config to your configured Appwrite Project",
112
+ "Deploy your local configuration (collections, attributes, indexes) to Appwrite",
110
113
  })
111
114
  .option("sync", {
112
115
  type: "boolean",
113
116
  description:
114
- "Synchronize by pulling your Appwrite config from your configured Appwrite Project",
117
+ "Pull and synchronize your local config with the remote Appwrite project schema",
115
118
  })
116
119
  .option("endpoint", {
117
120
  type: "string",
@@ -127,17 +130,17 @@ const argv = yargs(hideBin(process.argv))
127
130
  })
128
131
  .option("transfer", {
129
132
  type: "boolean",
130
- description: "Transfer data between databases or collections",
133
+ description: "Transfer documents and files between databases, collections, or projects",
131
134
  })
132
135
  .option("fromDbId", {
133
136
  alias: ["fromDb", "sourceDbId", "sourceDb"],
134
137
  type: "string",
135
- description: "Set the source database ID for transfer",
138
+ description: "Source database ID for transfer operations",
136
139
  })
137
140
  .option("toDbId", {
138
141
  alias: ["toDb", "targetDbId", "targetDb"],
139
142
  type: "string",
140
- description: "Set the destination database ID for transfer",
143
+ description: "Target database ID for transfer operations",
141
144
  })
142
145
  .option("fromCollectionId", {
143
146
  alias: ["fromCollId", "fromColl"],
@@ -171,7 +174,7 @@ const argv = yargs(hideBin(process.argv))
171
174
  })
172
175
  .option("setup", {
173
176
  type: "boolean",
174
- description: "Setup directories and files",
177
+ description: "Initialize project with configuration files and directory structure",
175
178
  })
176
179
  .option("updateFunctionSpec", {
177
180
  type: "boolean",
@@ -195,9 +198,17 @@ const argv = yargs(hideBin(process.argv))
195
198
  "s-8vcpu-8gb",
196
199
  ],
197
200
  })
201
+ .option("migrateConfig", {
202
+ alias: ["migrate"],
203
+ type: "boolean",
204
+ description: "Migrate appwriteConfig.ts to .appwrite structure with YAML configuration",
205
+ })
198
206
  .parse() as ParsedArgv;
199
207
 
200
208
  async function main() {
209
+ const startTime = Date.now();
210
+ const operationStats: Record<string, number> = {};
211
+
201
212
  if (argv.it) {
202
213
  const cli = new InteractiveCLI(process.cwd());
203
214
  await cli.run();
@@ -218,8 +229,14 @@ async function main() {
218
229
  return;
219
230
  }
220
231
 
232
+ if (argv.migrateConfig) {
233
+ const { migrateConfig } = await import("./utils/configMigration.js");
234
+ await migrateConfig(process.cwd());
235
+ return;
236
+ }
237
+
221
238
  if (!controller.config) {
222
- console.log(chalk.red("No Appwrite connection found"));
239
+ MessageFormatter.error("No Appwrite connection found", undefined, { prefix: "CLI" });
223
240
  return;
224
241
  }
225
242
 
@@ -248,10 +265,9 @@ async function main() {
248
265
  "Function ID and specification are required for updating function specs"
249
266
  );
250
267
  }
251
- console.log(
252
- chalk.yellow(
253
- `Updating function specification for ${parsedArgv.functionId} to ${parsedArgv.specification}, checking if specification exists...`
254
- )
268
+ MessageFormatter.info(
269
+ `Updating function specification for ${parsedArgv.functionId} to ${parsedArgv.specification}`,
270
+ { prefix: "Functions" }
255
271
  );
256
272
  const specifications = await listSpecifications(
257
273
  controller.appwriteServer!
@@ -261,8 +277,10 @@ async function main() {
261
277
  (s: { slug: string }) => s.slug === parsedArgv.specification
262
278
  )
263
279
  ) {
264
- console.log(
265
- chalk.red(`Specification ${parsedArgv.specification} not found`)
280
+ MessageFormatter.error(
281
+ `Specification ${parsedArgv.specification} not found`,
282
+ undefined,
283
+ { prefix: "Functions" }
266
284
  );
267
285
  return;
268
286
  }
@@ -276,7 +294,10 @@ async function main() {
276
294
  if (!options.databases || options.databases.length === 0) {
277
295
  const allDatabases = await fetchAllDatabases(controller.database!);
278
296
  options.databases = allDatabases.filter(
279
- (db) => db.name.toLowerCase() !== "migrations"
297
+ (db) => {
298
+ const useMigrations = controller.config?.useMigrations ?? true;
299
+ return useMigrations || db.name.toLowerCase() !== "migrations";
300
+ }
280
301
  );
281
302
  }
282
303
 
@@ -290,9 +311,12 @@ async function main() {
290
311
  }
291
312
 
292
313
  if (options.doBackup && options.databases) {
314
+ MessageFormatter.info(`Creating backups for ${options.databases.length} database(s)`, { prefix: "Backup" });
293
315
  for (const db of options.databases) {
294
316
  await controller.backupDatabase(db);
295
317
  }
318
+ operationStats.backups = options.databases.length;
319
+ MessageFormatter.success(`Backup completed for ${options.databases.length} database(s)`, { prefix: "Backup" });
296
320
  }
297
321
 
298
322
  if (
@@ -301,26 +325,46 @@ async function main() {
301
325
  options.wipeUsers ||
302
326
  options.wipeCollections
303
327
  ) {
328
+ // Confirm destructive operations
329
+ const databaseNames = options.databases?.map(db => db.name) || [];
330
+ const confirmed = await ConfirmationDialogs.confirmDatabaseWipe(databaseNames, {
331
+ includeStorage: options.wipeDocumentStorage,
332
+ includeUsers: options.wipeUsers
333
+ });
334
+
335
+ if (!confirmed) {
336
+ MessageFormatter.info("Operation cancelled by user", { prefix: "CLI" });
337
+ return;
338
+ }
339
+
340
+ let wipeStats = { databases: 0, collections: 0, users: 0, buckets: 0 };
341
+
304
342
  if (parsedArgv.wipe === "all") {
305
343
  if (options.databases) {
306
344
  for (const db of options.databases) {
307
345
  await controller.wipeDatabase(db, true); // true to wipe associated buckets
308
346
  }
347
+ wipeStats.databases = options.databases.length;
309
348
  }
310
349
  await controller.wipeUsers();
350
+ wipeStats.users = 1;
311
351
  } else if (parsedArgv.wipe === "docs") {
312
352
  if (options.databases) {
313
353
  for (const db of options.databases) {
314
354
  await controller.wipeBucketFromDatabase(db);
315
355
  }
356
+ wipeStats.databases = options.databases.length;
316
357
  }
317
358
  if (parsedArgv.bucketIds) {
318
- for (const bucketId of parsedArgv.bucketIds.split(",")) {
359
+ const bucketIds = parsedArgv.bucketIds.split(",");
360
+ for (const bucketId of bucketIds) {
319
361
  await controller.wipeDocumentStorage(bucketId);
320
362
  }
363
+ wipeStats.buckets = bucketIds.length;
321
364
  }
322
365
  } else if (parsedArgv.wipe === "users") {
323
366
  await controller.wipeUsers();
367
+ wipeStats.users = 1;
324
368
  }
325
369
 
326
370
  // Handle specific collection wipes
@@ -333,11 +377,30 @@ async function main() {
333
377
  const collectionsToWipe = dbCollections.filter((c) =>
334
378
  options.collections!.includes(c.$id)
335
379
  );
336
- for (const collection of collectionsToWipe) {
337
- await controller.wipeCollection(db, collection);
380
+
381
+ // Confirm collection wipe
382
+ const collectionNames = collectionsToWipe.map(c => c.name);
383
+ const collectionConfirmed = await ConfirmationDialogs.confirmCollectionWipe(
384
+ db.name,
385
+ collectionNames
386
+ );
387
+
388
+ if (collectionConfirmed) {
389
+ for (const collection of collectionsToWipe) {
390
+ await controller.wipeCollection(db, collection);
391
+ }
392
+ wipeStats.collections += collectionsToWipe.length;
338
393
  }
339
394
  }
340
395
  }
396
+
397
+ // Show wipe operation summary
398
+ if (wipeStats.databases > 0 || wipeStats.collections > 0 || wipeStats.users > 0 || wipeStats.buckets > 0) {
399
+ operationStats.wipedDatabases = wipeStats.databases;
400
+ operationStats.wipedCollections = wipeStats.collections;
401
+ operationStats.wipedUsers = wipeStats.users;
402
+ operationStats.wipedBuckets = wipeStats.buckets;
403
+ }
341
404
  }
342
405
 
343
406
  if (parsedArgv.push || parsedArgv.sync) {
@@ -359,17 +422,22 @@ async function main() {
359
422
 
360
423
  if (parsedArgv.push) {
361
424
  await controller.syncDb(databases, collections);
425
+ operationStats.pushedDatabases = databases.length;
426
+ operationStats.pushedCollections = collections.length;
362
427
  } else if (parsedArgv.sync) {
363
428
  await controller.synchronizeConfigurations(databases);
429
+ operationStats.syncedDatabases = databases.length;
364
430
  }
365
431
  }
366
432
 
367
433
  if (options.generateSchemas) {
368
434
  await controller.generateSchemas();
435
+ operationStats.generatedSchemas = 1;
369
436
  }
370
437
 
371
438
  if (options.importData) {
372
439
  await controller.importData(options);
440
+ operationStats.importCompleted = 1;
373
441
  }
374
442
 
375
443
  if (parsedArgv.transfer) {
@@ -380,16 +448,15 @@ async function main() {
380
448
 
381
449
  // Only fetch databases if database IDs are provided
382
450
  if (parsedArgv.fromDbId && parsedArgv.toDbId) {
383
- console.log(
384
- chalk.blue(
385
- `Starting database transfer from ${parsedArgv.fromDbId} to ${parsedArgv.toDbId}`
386
- )
451
+ MessageFormatter.info(
452
+ `Starting database transfer from ${parsedArgv.fromDbId} to ${parsedArgv.toDbId}`,
453
+ { prefix: "Transfer" }
387
454
  );
388
455
  fromDb = (
389
456
  await controller.getDatabasesByIds([parsedArgv.fromDbId])
390
457
  )?.[0];
391
458
  if (!fromDb) {
392
- console.log(chalk.red("Source database not found"));
459
+ MessageFormatter.error("Source database not found", undefined, { prefix: "Transfer" });
393
460
  return;
394
461
  }
395
462
  if (isRemote) {
@@ -410,19 +477,19 @@ async function main() {
410
477
  const remoteDbs = await fetchAllDatabases(targetDatabases);
411
478
  toDb = remoteDbs.find((db) => db.$id === parsedArgv.toDbId);
412
479
  if (!toDb) {
413
- console.log(chalk.red("Target database not found"));
480
+ MessageFormatter.error("Target database not found", undefined, { prefix: "Transfer" });
414
481
  return;
415
482
  }
416
483
  } else {
417
484
  toDb = (await controller.getDatabasesByIds([parsedArgv.toDbId]))?.[0];
418
485
  if (!toDb) {
419
- console.log(chalk.red("Target database not found"));
486
+ MessageFormatter.error("Target database not found", undefined, { prefix: "Transfer" });
420
487
  return;
421
488
  }
422
489
  }
423
490
 
424
491
  if (!fromDb || !toDb) {
425
- console.log(chalk.red("Source or target database not found"));
492
+ MessageFormatter.error("Source or target database not found", undefined, { prefix: "Transfer" });
426
493
  return;
427
494
  }
428
495
  }
@@ -470,11 +537,18 @@ async function main() {
470
537
  };
471
538
 
472
539
  await controller.transferData(transferOptions);
540
+ operationStats.transfers = 1;
541
+ }
542
+
543
+ // Show final operation summary if any operations were performed
544
+ if (Object.keys(operationStats).length > 0) {
545
+ const duration = Date.now() - startTime;
546
+ MessageFormatter.operationSummary("CLI Operations", operationStats, duration);
473
547
  }
474
548
  }
475
549
  }
476
550
 
477
551
  main().catch((error) => {
478
- console.error("An error occurred:", error);
552
+ MessageFormatter.error("CLI execution failed", error, { prefix: "CLI" });
479
553
  process.exit(1);
480
554
  });
@@ -11,7 +11,7 @@ import { InputFile } from "node-appwrite/file";
11
11
  import path from "path";
12
12
  import fs from "fs";
13
13
  import os from "os";
14
- import { logger } from "./logging.js";
14
+ import { logger } from "../shared/logging.js";
15
15
  import {
16
16
  tryAwaitWithRetry,
17
17
  type AfterImportActions,
@@ -485,7 +485,7 @@ export const afterImportActions = {
485
485
  // Use arrayBuffer if buffer is not available
486
486
  const arrayBuffer = await response.arrayBuffer();
487
487
  const buffer = Buffer.from(arrayBuffer);
488
- fs.writeFileSync(tempFilePath, buffer);
488
+ fs.writeFileSync(tempFilePath, new Uint8Array(buffer));
489
489
 
490
490
  // Create InputFile from the downloaded file
491
491
  const inputFile = InputFile.fromPath(tempFilePath, fileName);
@@ -1,4 +1,5 @@
1
- import { SchemaGenerator } from "./schemaStrings.js";
1
+ import { SchemaGenerator } from "../shared/schemaGenerator.js";
2
+ import { findYamlConfig } from "../config/yamlConfig.js";
2
3
  import {
3
4
  Client,
4
5
  Compression,
@@ -9,7 +10,7 @@ import {
9
10
  type Permission,
10
11
  } from "node-appwrite";
11
12
  import { fetchAllCollections } from "../collections/methods.js";
12
- import { fetchAllDatabases } from "./databases.js";
13
+ import { fetchAllDatabases } from "../databases/methods.js";
13
14
  import {
14
15
  CollectionSchema,
15
16
  attributeSchema,
@@ -92,7 +93,7 @@ export class AppwriteToX {
92
93
 
93
94
  // Loop through each database
94
95
  for (const database of databases) {
95
- if (database.name.toLowerCase() === "migrations") {
96
+ if (!this.config.useMigrations && database.name.toLowerCase() === "migrations") {
96
97
  continue;
97
98
  }
98
99
 
@@ -274,7 +275,19 @@ export class AppwriteToX {
274
275
  this.updatedConfig,
275
276
  this.appwriteFolderPath
276
277
  );
277
- generator.updateTsSchemas();
278
+
279
+ // Check if this is a YAML-based project
280
+ const yamlConfigPath = findYamlConfig(this.appwriteFolderPath);
281
+ const isYamlProject = !!yamlConfigPath;
282
+
283
+ if (isYamlProject) {
284
+ console.log("📄 Detected YAML configuration - generating YAML collection definitions");
285
+ generator.updateYamlCollections();
286
+ } else {
287
+ console.log("📝 Generating TypeScript collection definitions");
288
+ generator.updateTsSchemas();
289
+ }
290
+
278
291
  generator.generateSchemas();
279
292
  }
280
293
  }
@@ -14,14 +14,14 @@ import {
14
14
  } from "appwrite-utils";
15
15
  import path from "path";
16
16
  import fs from "fs";
17
- import { convertObjectByAttributeMappings } from "./converters.js";
17
+ import { convertObjectByAttributeMappings } from "../utils/dataConverters.js";
18
18
  import { z } from "zod";
19
19
  import { checkForCollection } from "../collections/methods.js";
20
20
  import { ID, Users, type Databases } from "node-appwrite";
21
- import { logger } from "./logging.js";
22
- import { findOrCreateOperation, updateOperation } from "./migrationHelper.js";
21
+ import { logger } from "../shared/logging.js";
22
+ import { findOrCreateOperation, updateOperation } from "../shared/migrationHelpers.js";
23
23
  import { AuthUserCreateSchema } from "../schemas/authUser.js";
24
- import { UsersController } from "./users.js";
24
+ import { UsersController } from "../users/methods.js";
25
25
  import { finalizeByAttributeMap } from "../utils/helperFunctions.js";
26
26
  import { isEmpty } from "es-toolkit/compat";
27
27
 
@@ -16,19 +16,21 @@ import type { ImportDataActions } from "./importDataActions.js";
16
16
  import { areCollectionNamesSame, tryAwaitWithRetry } from "../utils/index.js";
17
17
  import type { SetupOptions } from "../utilsController.js";
18
18
  import { resolveAndUpdateRelationships } from "./relationships.js";
19
- import { UsersController } from "./users.js";
20
- import { logger } from "./logging.js";
21
- import { updateOperation } from "./migrationHelper.js";
19
+ import { UsersController } from "../users/methods.js";
20
+ import { logger } from "../shared/logging.js";
21
+ import { updateOperation } from "../shared/migrationHelpers.js";
22
22
  import {
23
23
  BatchSchema,
24
24
  OperationCreateSchema,
25
25
  OperationSchema,
26
- } from "./backup.js";
26
+ } from "../storage/schemas.js";
27
27
  import { DataLoader, type CollectionImportData } from "./dataLoader.js";
28
28
  import {
29
29
  transferDatabaseLocalToLocal,
30
30
  transferStorageLocalToLocal,
31
31
  } from "./transfer.js";
32
+ import { MessageFormatter } from "../shared/messageFormatter.js";
33
+ import { ProgressManager } from "../shared/progressManager.js";
32
34
 
33
35
  export class ImportController {
34
36
  private config: AppwriteConfig;
@@ -82,13 +84,11 @@ export class ImportController {
82
84
  let databaseRan: Models.Database | undefined;
83
85
 
84
86
  for (let db of databasesToProcess) {
85
- if (db.name.toLowerCase().trim().replace(" ", "") === "migrations") {
87
+ if (!this.config.useMigrations && db.name.toLowerCase().trim().replace(" ", "") === "migrations") {
86
88
  continue;
87
89
  }
88
90
 
89
- console.log(`---------------------------------`);
90
- console.log(`Starting import data for database: ${db.name}`);
91
- console.log(`---------------------------------`);
91
+ MessageFormatter.banner(`Starting import data for database: ${db.name}`, "Database Import");
92
92
 
93
93
  if (!databaseRan) {
94
94
  databaseRan = db;
@@ -286,14 +286,18 @@ export class ImportController {
286
286
  continue;
287
287
  }
288
288
 
289
- const importOperation = await this.database.getDocument(
290
- "migrations",
291
- "currentOperations",
292
- importOperationId
293
- );
294
- await updateOperation(this.database, importOperation.$id, {
295
- status: "in_progress",
296
- });
289
+ let importOperation: any = null;
290
+ if (this.config.useMigrations) {
291
+ importOperation = await this.database.getDocument(
292
+ "migrations",
293
+ "currentOperations",
294
+ importOperationId
295
+ );
296
+ await updateOperation(this.database, importOperation.$id, {
297
+ status: "in_progress",
298
+ }, this.config.useMigrations);
299
+ }
300
+
297
301
  const collectionData = dataLoader.importMap.get(
298
302
  dataLoader.getCollectionKey(collection.name)
299
303
  );
@@ -344,14 +348,18 @@ export class ImportController {
344
348
  // Wait for all promises in the current batch to resolve
345
349
  await Promise.all(batchPromises);
346
350
  console.log(`Completed batch ${i + 1} of ${dataSplit.length}`);
347
- await updateOperation(this.database, importOperation.$id, {
348
- progress: processedItems,
349
- });
351
+ if (this.config.useMigrations && importOperation) {
352
+ await updateOperation(this.database, importOperation.$id, {
353
+ progress: processedItems,
354
+ }, this.config.useMigrations);
355
+ }
350
356
  }
351
357
  // After all batches are processed, update the operation status to completed
352
- await updateOperation(this.database, importOperation.$id, {
353
- status: "completed",
354
- });
358
+ if (this.config.useMigrations && importOperation) {
359
+ await updateOperation(this.database, importOperation.$id, {
360
+ status: "completed",
361
+ }, this.config.useMigrations);
362
+ }
355
363
  }
356
364
  }
357
365
  }
@@ -6,10 +6,10 @@ import {
6
6
  type AttributeMappings,
7
7
  } from "appwrite-utils";
8
8
  import { converterFunctions, type ConverterFunctions } from "appwrite-utils";
9
- import { convertObjectBySchema } from "./converters.js";
9
+ import { convertObjectBySchema } from "../utils/dataConverters.js";
10
10
  import { type AfterImportActions } from "appwrite-utils";
11
11
  import { afterImportActions } from "./afterImportActions.js";
12
- import { logger } from "./logging.js";
12
+ import { logger } from "../shared/logging.js";
13
13
  import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
14
14
 
15
15
  export class ImportDataActions {
@@ -5,7 +5,7 @@ import type {
5
5
  Attribute,
6
6
  RelationshipAttribute,
7
7
  } from "appwrite-utils";
8
- import { logger } from "./logging.js";
8
+ import { logger } from "../shared/logging.js";
9
9
 
10
10
  /**
11
11
  * Finds collections that have defined relationship attributes.