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.
- package/.appwrite/.yaml_schemas/appwrite-config.schema.json +380 -0
- package/.appwrite/.yaml_schemas/collection.schema.json +255 -0
- package/.appwrite/collections/Categories.yaml +182 -0
- package/.appwrite/collections/ExampleCollection.yaml +36 -0
- package/.appwrite/collections/Posts.yaml +227 -0
- package/.appwrite/collections/Users.yaml +149 -0
- package/.appwrite/config.yaml +109 -0
- package/.appwrite/import/README.md +148 -0
- package/.appwrite/import/categories-import.yaml +129 -0
- package/.appwrite/import/posts-import.yaml +208 -0
- package/.appwrite/import/users-import.yaml +130 -0
- package/.appwrite/importData/categories.json +194 -0
- package/.appwrite/importData/posts.json +270 -0
- package/.appwrite/importData/users.json +220 -0
- package/.appwrite/schemas/categories.json +128 -0
- package/.appwrite/schemas/exampleCollection.json +52 -0
- package/.appwrite/schemas/posts.json +173 -0
- package/.appwrite/schemas/users.json +125 -0
- package/README.md +260 -33
- package/dist/collections/attributes.js +3 -2
- package/dist/collections/methods.js +56 -38
- package/dist/config/yamlConfig.d.ts +501 -0
- package/dist/config/yamlConfig.js +452 -0
- package/dist/databases/setup.d.ts +6 -0
- package/dist/databases/setup.js +119 -0
- package/dist/functions/methods.d.ts +1 -1
- package/dist/functions/methods.js +5 -2
- package/dist/functions/openapi.d.ts +4 -0
- package/dist/functions/openapi.js +60 -0
- package/dist/interactiveCLI.d.ts +5 -0
- package/dist/interactiveCLI.js +194 -49
- package/dist/main.js +91 -30
- package/dist/migrations/afterImportActions.js +2 -2
- package/dist/migrations/appwriteToX.d.ts +10 -0
- package/dist/migrations/appwriteToX.js +15 -4
- package/dist/migrations/backup.d.ts +16 -16
- package/dist/migrations/dataLoader.d.ts +83 -1
- package/dist/migrations/dataLoader.js +4 -4
- package/dist/migrations/importController.js +25 -18
- package/dist/migrations/importDataActions.js +2 -2
- package/dist/migrations/logging.d.ts +9 -1
- package/dist/migrations/logging.js +41 -22
- package/dist/migrations/migrationHelper.d.ts +4 -4
- package/dist/migrations/relationships.js +1 -1
- package/dist/migrations/services/DataTransformationService.d.ts +55 -0
- package/dist/migrations/services/DataTransformationService.js +158 -0
- package/dist/migrations/services/FileHandlerService.d.ts +75 -0
- package/dist/migrations/services/FileHandlerService.js +236 -0
- package/dist/migrations/services/ImportOrchestrator.d.ts +97 -0
- package/dist/migrations/services/ImportOrchestrator.js +488 -0
- package/dist/migrations/services/RateLimitManager.d.ts +138 -0
- package/dist/migrations/services/RateLimitManager.js +279 -0
- package/dist/migrations/services/RelationshipResolver.d.ts +120 -0
- package/dist/migrations/services/RelationshipResolver.js +332 -0
- package/dist/migrations/services/UserMappingService.d.ts +109 -0
- package/dist/migrations/services/UserMappingService.js +277 -0
- package/dist/migrations/services/ValidationService.d.ts +74 -0
- package/dist/migrations/services/ValidationService.js +260 -0
- package/dist/migrations/transfer.d.ts +0 -6
- package/dist/migrations/transfer.js +16 -132
- package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +384 -0
- package/dist/migrations/yaml/YamlImportConfigLoader.js +375 -0
- package/dist/migrations/yaml/YamlImportIntegration.d.ts +87 -0
- package/dist/migrations/yaml/YamlImportIntegration.js +330 -0
- package/dist/migrations/yaml/generateImportSchemas.d.ts +17 -0
- package/dist/migrations/yaml/generateImportSchemas.js +575 -0
- package/dist/schemas/authUser.d.ts +9 -9
- package/dist/shared/attributeManager.d.ts +17 -0
- package/dist/shared/attributeManager.js +273 -0
- package/dist/shared/confirmationDialogs.d.ts +75 -0
- package/dist/shared/confirmationDialogs.js +236 -0
- package/dist/shared/functionManager.d.ts +48 -0
- package/dist/shared/functionManager.js +322 -0
- package/dist/shared/indexManager.d.ts +24 -0
- package/dist/shared/indexManager.js +150 -0
- package/dist/shared/jsonSchemaGenerator.d.ts +51 -0
- package/dist/shared/jsonSchemaGenerator.js +313 -0
- package/dist/shared/logging.d.ts +10 -0
- package/dist/shared/logging.js +46 -0
- package/dist/shared/messageFormatter.d.ts +37 -0
- package/dist/shared/messageFormatter.js +152 -0
- package/dist/shared/migrationHelpers.d.ts +173 -0
- package/dist/shared/migrationHelpers.js +142 -0
- package/dist/shared/operationLogger.d.ts +3 -0
- package/dist/shared/operationLogger.js +25 -0
- package/dist/shared/operationQueue.d.ts +13 -0
- package/dist/shared/operationQueue.js +79 -0
- package/dist/shared/progressManager.d.ts +62 -0
- package/dist/shared/progressManager.js +215 -0
- package/dist/shared/schemaGenerator.d.ts +18 -0
- package/dist/shared/schemaGenerator.js +523 -0
- package/dist/storage/methods.d.ts +3 -1
- package/dist/storage/methods.js +144 -55
- package/dist/storage/schemas.d.ts +56 -16
- package/dist/types.d.ts +2 -2
- package/dist/types.js +1 -1
- package/dist/users/methods.d.ts +16 -0
- package/dist/users/methods.js +276 -0
- package/dist/utils/configMigration.d.ts +1 -0
- package/dist/utils/configMigration.js +156 -0
- package/dist/utils/dataConverters.d.ts +46 -0
- package/dist/utils/dataConverters.js +139 -0
- package/dist/utils/loadConfigs.d.ts +15 -4
- package/dist/utils/loadConfigs.js +377 -51
- package/dist/utils/schemaStrings.js +2 -1
- package/dist/utils/setupFiles.d.ts +2 -1
- package/dist/utils/setupFiles.js +723 -28
- package/dist/utils/validationRules.d.ts +43 -0
- package/dist/utils/validationRules.js +42 -0
- package/dist/utils/yamlConverter.d.ts +48 -0
- package/dist/utils/yamlConverter.js +98 -0
- package/dist/utilsController.js +65 -43
- package/package.json +19 -15
- package/src/collections/attributes.ts +3 -2
- package/src/collections/methods.ts +85 -51
- package/src/config/yamlConfig.ts +488 -0
- package/src/{migrations/setupDatabase.ts → databases/setup.ts} +11 -5
- package/src/functions/methods.ts +8 -4
- package/src/functions/templates/count-docs-in-collection/package.json +25 -0
- package/src/functions/templates/count-docs-in-collection/tsconfig.json +28 -0
- package/src/functions/templates/typescript-node/package.json +24 -0
- package/src/functions/templates/typescript-node/tsconfig.json +28 -0
- package/src/functions/templates/uv/README.md +31 -0
- package/src/functions/templates/uv/pyproject.toml +29 -0
- package/src/interactiveCLI.ts +226 -61
- package/src/main.ts +111 -37
- package/src/migrations/afterImportActions.ts +2 -2
- package/src/migrations/appwriteToX.ts +17 -4
- package/src/migrations/dataLoader.ts +4 -4
- package/src/migrations/importController.ts +30 -22
- package/src/migrations/importDataActions.ts +2 -2
- package/src/migrations/relationships.ts +1 -1
- package/src/migrations/services/DataTransformationService.ts +196 -0
- package/src/migrations/services/FileHandlerService.ts +311 -0
- package/src/migrations/services/ImportOrchestrator.ts +669 -0
- package/src/migrations/services/RateLimitManager.ts +363 -0
- package/src/migrations/services/RelationshipResolver.ts +461 -0
- package/src/migrations/services/UserMappingService.ts +345 -0
- package/src/migrations/services/ValidationService.ts +349 -0
- package/src/migrations/transfer.ts +22 -228
- package/src/migrations/yaml/YamlImportConfigLoader.ts +427 -0
- package/src/migrations/yaml/YamlImportIntegration.ts +419 -0
- package/src/migrations/yaml/generateImportSchemas.ts +589 -0
- package/src/shared/attributeManager.ts +429 -0
- package/src/shared/confirmationDialogs.ts +327 -0
- package/src/shared/functionManager.ts +515 -0
- package/src/shared/indexManager.ts +253 -0
- package/src/shared/jsonSchemaGenerator.ts +403 -0
- package/src/shared/logging.ts +74 -0
- package/src/shared/messageFormatter.ts +195 -0
- package/src/{migrations/migrationHelper.ts → shared/migrationHelpers.ts} +22 -4
- package/src/{migrations/helper.ts → shared/operationLogger.ts} +7 -2
- package/src/{migrations/queue.ts → shared/operationQueue.ts} +1 -1
- package/src/shared/progressManager.ts +278 -0
- package/src/{migrations/schemaStrings.ts → shared/schemaGenerator.ts} +71 -17
- package/src/storage/methods.ts +199 -78
- package/src/types.ts +2 -2
- package/src/{migrations/users.ts → users/methods.ts} +2 -2
- package/src/utils/configMigration.ts +212 -0
- package/src/utils/loadConfigs.ts +414 -52
- package/src/utils/schemaStrings.ts +2 -1
- package/src/utils/setupFiles.ts +742 -40
- package/src/{migrations → utils}/validationRules.ts +1 -1
- package/src/utils/yamlConverter.ts +131 -0
- package/src/utilsController.ts +75 -54
- package/src/functions/templates/poetry/README.md +0 -30
- package/src/functions/templates/poetry/pyproject.toml +0 -16
- package/src/migrations/attributes.ts +0 -561
- package/src/migrations/backup.ts +0 -205
- package/src/migrations/databases.ts +0 -39
- package/src/migrations/dbHelpers.ts +0 -92
- package/src/migrations/indexes.ts +0 -40
- package/src/migrations/logging.ts +0 -29
- package/src/migrations/storage.ts +0 -538
- /package/src/{migrations → functions}/openapi.ts +0 -0
- /package/src/functions/templates/{poetry → uv}/src/__init__.py +0 -0
- /package/src/functions/templates/{poetry → uv}/src/index.py +0 -0
- /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 "./
|
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
|
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: "
|
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
|
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
|
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:
|
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
|
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: "
|
103
|
+
description: "Create a complete backup of your databases and collections",
|
101
104
|
})
|
102
105
|
.option("writeData", {
|
103
106
|
type: "boolean",
|
104
|
-
description: "
|
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
|
-
"
|
112
|
+
"Deploy your local configuration (collections, attributes, indexes) to Appwrite",
|
110
113
|
})
|
111
114
|
.option("sync", {
|
112
115
|
type: "boolean",
|
113
116
|
description:
|
114
|
-
"
|
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
|
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: "
|
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: "
|
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: "
|
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
|
-
|
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
|
-
|
252
|
-
|
253
|
-
|
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
|
-
|
265
|
-
|
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) =>
|
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
|
-
|
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
|
-
|
337
|
-
|
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
|
-
|
384
|
-
|
385
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 "
|
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 "
|
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 "
|
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
|
-
|
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 "
|
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 "
|
22
|
-
import { findOrCreateOperation, updateOperation } from "
|
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 "
|
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 "
|
20
|
-
import { logger } from "
|
21
|
-
import { updateOperation } from "
|
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 "
|
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
|
-
|
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
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
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
|
-
|
348
|
-
|
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
|
-
|
353
|
-
|
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 "
|
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 "
|
12
|
+
import { logger } from "../shared/logging.js";
|
13
13
|
import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
|
14
14
|
|
15
15
|
export class ImportDataActions {
|