appwrite-utils-cli 0.9.2 → 0.9.4
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/README.md +3 -1
- package/dist/interactiveCLI.d.ts +3 -2
- package/dist/interactiveCLI.js +28 -59
- package/dist/main.js +18 -3
- package/dist/migrations/setupDatabase.js +28 -6
- package/dist/setupCommands.d.ts +1 -0
- package/dist/setupCommands.js +1 -0
- package/dist/setupController.d.ts +6 -0
- package/dist/setupController.js +17 -0
- package/dist/utils/schemaStrings.js +37 -37
- package/dist/utils/setupFiles.d.ts +1 -1
- package/dist/utils/setupFiles.js +2 -2
- package/dist/utilsController.js +2 -0
- package/package.json +53 -53
- package/src/collections/attributes.ts +483 -483
- package/src/collections/indexes.ts +53 -53
- package/src/collections/methods.ts +331 -331
- package/src/interactiveCLI.ts +722 -767
- package/src/main.ts +20 -3
- package/src/migrations/helper.ts +40 -40
- package/src/migrations/setupDatabase.ts +54 -21
- package/src/migrations/transfer.ts +608 -608
- package/src/setupCommands.ts +0 -0
- package/src/setupController.ts +25 -0
- package/src/storage/methods.ts +371 -371
- package/src/storage/schemas.ts +205 -205
- package/src/utils/getClientFromConfig.ts +17 -17
- package/src/utils/retryFailedPromises.ts +27 -27
- package/src/utils/schemaStrings.ts +473 -473
- package/src/utils/setupFiles.ts +5 -2
- package/src/utilsController.ts +1 -0
package/README.md
CHANGED
@@ -80,6 +80,7 @@ Available options:
|
|
80
80
|
- `--remoteEndpoint`: Set the remote Appwrite endpoint for transfers
|
81
81
|
- `--remoteProjectId`: Set the remote Appwrite project ID for transfers
|
82
82
|
- `--remoteApiKey`: Set the remote Appwrite API key for transfers
|
83
|
+
- `--setup`: Create setup files
|
83
84
|
|
84
85
|
## Examples
|
85
86
|
|
@@ -123,7 +124,8 @@ This updated CLI ensures that developers have robust tools at their fingertips t
|
|
123
124
|
|
124
125
|
## Changelog
|
125
126
|
|
126
|
-
- 0.9.
|
127
|
+
- 0.9.4: Fixed migrations database ensuring it has the required collections
|
128
|
+
- 0.9.3: Fixed deployment error && fix lack of existing `appwriteConfig.ts` file from causing error (you want to be able to setup yeah? haha)
|
127
129
|
- 0.9.2: Added changelog back, whoops
|
128
130
|
- 0.0.90: Updated README with new command-line options and fixed alias issues
|
129
131
|
- 0.0.74: Added `--backup` support, even if only one database
|
package/dist/interactiveCLI.d.ts
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
import { UtilsController } from "./utilsController.js";
|
2
1
|
export declare class InteractiveCLI {
|
2
|
+
private currentDir;
|
3
3
|
private controller;
|
4
|
-
constructor(currentDir
|
4
|
+
constructor(currentDir: string);
|
5
5
|
run(): Promise<void>;
|
6
|
+
private initControllerIfNeeded;
|
6
7
|
private selectDatabases;
|
7
8
|
private selectCollections;
|
8
9
|
private selectBuckets;
|
package/dist/interactiveCLI.js
CHANGED
@@ -22,22 +22,14 @@ var CHOICES;
|
|
22
22
|
CHOICES["EXIT"] = "Exit";
|
23
23
|
})(CHOICES || (CHOICES = {}));
|
24
24
|
export class InteractiveCLI {
|
25
|
+
currentDir;
|
25
26
|
controller;
|
26
|
-
constructor(currentDir
|
27
|
-
|
28
|
-
this.controller = utilsController;
|
29
|
-
}
|
30
|
-
else if (currentDir) {
|
31
|
-
this.controller = new UtilsController(currentDir);
|
32
|
-
}
|
33
|
-
else {
|
34
|
-
throw new Error("Current directory or utils controller is required");
|
35
|
-
}
|
27
|
+
constructor(currentDir) {
|
28
|
+
this.currentDir = currentDir;
|
36
29
|
}
|
37
30
|
async run() {
|
38
31
|
console.log("Welcome to Appwrite Utils CLI Tool by Zach Handley");
|
39
32
|
console.log("For more information, visit https://github.com/zachhandley/appwrite-utils");
|
40
|
-
await this.controller.init();
|
41
33
|
while (true) {
|
42
34
|
const { action } = await inquirer.prompt([
|
43
35
|
{
|
@@ -52,30 +44,37 @@ export class InteractiveCLI {
|
|
52
44
|
await this.createCollectionConfig();
|
53
45
|
break;
|
54
46
|
case CHOICES.SETUP_DIRS_FILES:
|
55
|
-
await setupDirsFiles(false);
|
47
|
+
await setupDirsFiles(false, this.currentDir);
|
56
48
|
break;
|
57
49
|
case CHOICES.SETUP_DIRS_FILES_WITH_EXAMPLE_DATA:
|
58
|
-
await setupDirsFiles(true);
|
50
|
+
await setupDirsFiles(true, this.currentDir);
|
59
51
|
break;
|
60
52
|
case CHOICES.SYNCHRONIZE_CONFIGURATIONS:
|
53
|
+
await this.initControllerIfNeeded();
|
61
54
|
await this.synchronizeConfigurations();
|
62
55
|
break;
|
63
56
|
case CHOICES.SYNC_DB:
|
57
|
+
await this.initControllerIfNeeded();
|
64
58
|
await this.syncDb();
|
65
59
|
break;
|
66
60
|
case CHOICES.TRANSFER_DATA:
|
61
|
+
await this.initControllerIfNeeded();
|
67
62
|
await this.transferData();
|
68
63
|
break;
|
69
64
|
case CHOICES.BACKUP_DATABASE:
|
65
|
+
await this.initControllerIfNeeded();
|
70
66
|
await this.backupDatabase();
|
71
67
|
break;
|
72
68
|
case CHOICES.WIPE_DATABASE:
|
69
|
+
await this.initControllerIfNeeded();
|
73
70
|
await this.wipeDatabase();
|
74
71
|
break;
|
75
72
|
case CHOICES.GENERATE_SCHEMAS:
|
73
|
+
await this.initControllerIfNeeded();
|
76
74
|
await this.generateSchemas();
|
77
75
|
break;
|
78
76
|
case CHOICES.IMPORT_DATA:
|
77
|
+
await this.initControllerIfNeeded();
|
79
78
|
await this.importData();
|
80
79
|
break;
|
81
80
|
case CHOICES.EXIT:
|
@@ -84,12 +83,14 @@ export class InteractiveCLI {
|
|
84
83
|
}
|
85
84
|
}
|
86
85
|
}
|
86
|
+
async initControllerIfNeeded() {
|
87
|
+
if (!this.controller) {
|
88
|
+
this.controller = new UtilsController(this.currentDir);
|
89
|
+
await this.controller.init();
|
90
|
+
}
|
91
|
+
}
|
87
92
|
async selectDatabases(databases, message, multiSelect = true) {
|
88
93
|
const choices = databases.map((db) => ({ name: db.name, value: db }));
|
89
|
-
if (multiSelect) {
|
90
|
-
choices.unshift({ name: "Select All", value: "ALL" });
|
91
|
-
choices.push({ name: "Clear Selection", value: "CLEAR" });
|
92
|
-
}
|
93
94
|
const { selectedDatabases } = await inquirer.prompt([
|
94
95
|
{
|
95
96
|
type: multiSelect ? "checkbox" : "list",
|
@@ -100,15 +101,7 @@ export class InteractiveCLI {
|
|
100
101
|
pageSize: 10,
|
101
102
|
},
|
102
103
|
]);
|
103
|
-
|
104
|
-
if (selectedDatabases.includes("ALL")) {
|
105
|
-
return databases;
|
106
|
-
}
|
107
|
-
else if (selectedDatabases.includes("CLEAR")) {
|
108
|
-
return [];
|
109
|
-
}
|
110
|
-
}
|
111
|
-
return selectedDatabases.filter((db) => typeof db !== "string");
|
104
|
+
return selectedDatabases;
|
112
105
|
}
|
113
106
|
async selectCollections(database, databasesClient, message, multiSelect = true) {
|
114
107
|
const collections = await fetchAllCollections(database.$id, databasesClient);
|
@@ -116,10 +109,6 @@ export class InteractiveCLI {
|
|
116
109
|
name: collection.name,
|
117
110
|
value: collection,
|
118
111
|
}));
|
119
|
-
if (multiSelect) {
|
120
|
-
choices.unshift({ name: "Select All", value: "ALL" });
|
121
|
-
choices.push({ name: "Clear Selection", value: "CLEAR" });
|
122
|
-
}
|
123
112
|
const { selectedCollections } = await inquirer.prompt([
|
124
113
|
{
|
125
114
|
type: multiSelect ? "checkbox" : "list",
|
@@ -130,25 +119,13 @@ export class InteractiveCLI {
|
|
130
119
|
pageSize: 10,
|
131
120
|
},
|
132
121
|
]);
|
133
|
-
|
134
|
-
if (selectedCollections.includes("ALL")) {
|
135
|
-
return collections;
|
136
|
-
}
|
137
|
-
else if (selectedCollections.includes("CLEAR")) {
|
138
|
-
return [];
|
139
|
-
}
|
140
|
-
}
|
141
|
-
return selectedCollections.filter((collection) => typeof collection !== "string");
|
122
|
+
return selectedCollections;
|
142
123
|
}
|
143
124
|
async selectBuckets(buckets, message, multiSelect = true) {
|
144
125
|
const choices = buckets.map((bucket) => ({
|
145
126
|
name: bucket.name,
|
146
|
-
value: bucket
|
127
|
+
value: bucket,
|
147
128
|
}));
|
148
|
-
if (multiSelect) {
|
149
|
-
choices.unshift({ name: "Select All", value: "ALL" });
|
150
|
-
choices.push({ name: "Clear Selection", value: "CLEAR" });
|
151
|
-
}
|
152
129
|
const { selectedBuckets } = await inquirer.prompt([
|
153
130
|
{
|
154
131
|
type: multiSelect ? "checkbox" : "list",
|
@@ -159,15 +136,7 @@ export class InteractiveCLI {
|
|
159
136
|
pageSize: 10,
|
160
137
|
},
|
161
138
|
]);
|
162
|
-
|
163
|
-
if (selectedBuckets.includes("ALL")) {
|
164
|
-
return buckets;
|
165
|
-
}
|
166
|
-
else if (selectedBuckets.includes("CLEAR")) {
|
167
|
-
return [];
|
168
|
-
}
|
169
|
-
}
|
170
|
-
return selectedBuckets.map((id) => buckets.find((bucket) => bucket.$id === id));
|
139
|
+
return selectedBuckets;
|
171
140
|
}
|
172
141
|
async createCollectionConfig() {
|
173
142
|
const { collectionName } = await inquirer.prompt([
|
@@ -360,7 +329,7 @@ export class InteractiveCLI {
|
|
360
329
|
throw new Error("Database is not initialized. Is the config file correct and created?");
|
361
330
|
}
|
362
331
|
const databases = await fetchAllDatabases(this.controller.database);
|
363
|
-
const selectedDatabases = await this.selectDatabases(databases, "Select databases to synchronize
|
332
|
+
const selectedDatabases = await this.selectDatabases(databases, "Select databases to synchronize:");
|
364
333
|
console.log("Configuring storage buckets...");
|
365
334
|
const updatedConfig = await this.configureBuckets(this.controller.config, selectedDatabases);
|
366
335
|
console.log("Synchronizing configurations...");
|
@@ -371,7 +340,7 @@ export class InteractiveCLI {
|
|
371
340
|
throw new Error("Database is not initialized, is the config file correct & created?");
|
372
341
|
}
|
373
342
|
const databases = await fetchAllDatabases(this.controller.database);
|
374
|
-
const selectedDatabases = await this.selectDatabases(databases, "Select databases to backup
|
343
|
+
const selectedDatabases = await this.selectDatabases(databases, "Select databases to backup:");
|
375
344
|
for (const db of selectedDatabases) {
|
376
345
|
console.log(`Backing up database: ${db.name}`);
|
377
346
|
await this.controller.backupDatabase(db);
|
@@ -383,12 +352,12 @@ export class InteractiveCLI {
|
|
383
352
|
}
|
384
353
|
const databases = await fetchAllDatabases(this.controller.database);
|
385
354
|
const storage = await listBuckets(this.controller.storage);
|
386
|
-
const selectedDatabases = await this.selectDatabases(databases, "Select databases to wipe
|
355
|
+
const selectedDatabases = await this.selectDatabases(databases, "Select databases to wipe:");
|
387
356
|
const { selectedStorage } = await inquirer.prompt([
|
388
357
|
{
|
389
358
|
type: "checkbox",
|
390
359
|
name: "selectedStorage",
|
391
|
-
message: "Select storage buckets to wipe
|
360
|
+
message: "Select storage buckets to wipe:",
|
392
361
|
choices: storage.buckets.map((s) => ({ name: s.name, value: s.$id })),
|
393
362
|
},
|
394
363
|
]);
|
@@ -436,7 +405,7 @@ export class InteractiveCLI {
|
|
436
405
|
const selectedDatabases = await this.selectDatabases(databases, "Select the database(s) to import data into:");
|
437
406
|
let selectedCollections = [];
|
438
407
|
for (const db of selectedDatabases) {
|
439
|
-
const dbCollections = await this.selectCollections(db, this.controller.database, `Select collections to import data into for database ${db.name}
|
408
|
+
const dbCollections = await this.selectCollections(db, this.controller.database, `Select collections to import data into for database ${db.name}:`, true);
|
440
409
|
selectedCollections = [...selectedCollections, ...dbCollections];
|
441
410
|
}
|
442
411
|
const { shouldWriteFile } = await inquirer.prompt([
|
@@ -511,7 +480,7 @@ export class InteractiveCLI {
|
|
511
480
|
}
|
512
481
|
const [fromDb] = await this.selectDatabases(sourceDatabases, "Select the source database:", false);
|
513
482
|
const [targetDb] = await this.selectDatabases(targetDatabases.filter((db) => db.$id !== fromDb.$id), "Select the target database:", false);
|
514
|
-
const selectedCollections = await this.selectCollections(fromDb, sourceClient, "Select collections to transfer
|
483
|
+
const selectedCollections = await this.selectCollections(fromDb, sourceClient, "Select collections to transfer):");
|
515
484
|
const { transferStorage } = await inquirer.prompt([
|
516
485
|
{
|
517
486
|
type: "confirm",
|
package/dist/main.js
CHANGED
@@ -110,18 +110,33 @@ const argv = yargs(hideBin(process.argv))
|
|
110
110
|
.option("remoteApiKey", {
|
111
111
|
type: "string",
|
112
112
|
description: "Set the remote Appwrite API key for transfers",
|
113
|
+
})
|
114
|
+
.option("setup", {
|
115
|
+
type: "boolean",
|
116
|
+
description: "Setup the project with example data",
|
113
117
|
})
|
114
118
|
.help()
|
115
119
|
.parse();
|
116
120
|
async function main() {
|
117
121
|
const parsedArgv = (await argv);
|
118
|
-
|
119
|
-
await controller.init();
|
122
|
+
let controller;
|
120
123
|
if (parsedArgv.it) {
|
121
|
-
|
124
|
+
try {
|
125
|
+
controller = new UtilsController(process.cwd());
|
126
|
+
await controller.init();
|
127
|
+
}
|
128
|
+
catch (error) {
|
129
|
+
// If it fails, that means there's no config, more than likely
|
130
|
+
console.log("No config found, you probably need to create the setup files");
|
131
|
+
}
|
132
|
+
const cli = new InteractiveCLI(process.cwd());
|
122
133
|
await cli.run();
|
123
134
|
}
|
124
135
|
else {
|
136
|
+
if (!controller) {
|
137
|
+
controller = new UtilsController(process.cwd());
|
138
|
+
await controller.init();
|
139
|
+
}
|
125
140
|
// Handle non-interactive mode with the new options
|
126
141
|
const options = {
|
127
142
|
databases: parsedArgv.dbIds
|
@@ -9,7 +9,7 @@ export const setupMigrationDatabase = async (config) => {
|
|
9
9
|
console.log("Starting Migrations Setup");
|
10
10
|
console.log("---------------------------------");
|
11
11
|
const database = new Databases(config.appwriteClient);
|
12
|
-
let db
|
12
|
+
let db;
|
13
13
|
const migrationCollectionsSetup = getMigrationCollectionSchemas();
|
14
14
|
try {
|
15
15
|
db = await tryAwaitWithRetry(async () => await database.get("migrations"), undefined, true);
|
@@ -19,18 +19,40 @@ export const setupMigrationDatabase = async (config) => {
|
|
19
19
|
db = await tryAwaitWithRetry(async () => await database.create("migrations", "Migrations", true));
|
20
20
|
console.log("Migrations database created");
|
21
21
|
}
|
22
|
+
if (!db) {
|
23
|
+
console.error("Failed to create or retrieve the migrations database");
|
24
|
+
return;
|
25
|
+
}
|
22
26
|
for (const [collectionName, { collection, attributes }] of Object.entries(migrationCollectionsSetup)) {
|
23
27
|
const collectionId = toCamelCase(collectionName);
|
24
|
-
let collectionFound
|
28
|
+
let collectionFound;
|
25
29
|
try {
|
26
|
-
collectionFound = await tryAwaitWithRetry(async () => await database.getCollection(db.$id, collectionId));
|
30
|
+
collectionFound = await tryAwaitWithRetry(async () => await database.getCollection(db.$id, collectionId), undefined, true);
|
31
|
+
console.log(`Collection found: ${collectionId}`);
|
27
32
|
}
|
28
33
|
catch (e) {
|
29
34
|
console.log(`Collection not found: ${collectionId}`);
|
30
|
-
|
35
|
+
try {
|
36
|
+
collectionFound = await tryAwaitWithRetry(async () => await database.createCollection(db.$id, collectionId, collectionName, undefined, collection.documentSecurity, collection.enabled), undefined, true);
|
37
|
+
console.log(`Collection created: ${collectionId}`);
|
38
|
+
}
|
39
|
+
catch (createError) {
|
40
|
+
console.error(`Failed to create collection: ${collectionId}`, createError);
|
41
|
+
continue;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
if (!collectionFound) {
|
45
|
+
console.error(`Failed to create or retrieve collection: ${collectionId}`);
|
46
|
+
continue;
|
31
47
|
}
|
32
48
|
for (const attribute of attributes) {
|
33
|
-
|
49
|
+
try {
|
50
|
+
await createOrUpdateAttribute(database, db.$id, collectionFound, attribute);
|
51
|
+
console.log(`Attribute created/updated: ${attribute.key}`);
|
52
|
+
}
|
53
|
+
catch (attrError) {
|
54
|
+
console.error(`Failed to create/update attribute: ${attribute.key}`, attrError);
|
55
|
+
}
|
34
56
|
}
|
35
57
|
}
|
36
58
|
console.log("---------------------------------");
|
@@ -43,7 +65,7 @@ export const ensureDatabasesExist = async (config) => {
|
|
43
65
|
const existingDatabases = await tryAwaitWithRetry(async () => await database.list([Query.limit(500)]));
|
44
66
|
const migrationsDatabase = existingDatabases.databases.find((d) => d.name.toLowerCase().trim().replace(" ", "") === "migrations");
|
45
67
|
if (existingDatabases.databases.length !== 0 && migrationsDatabase) {
|
46
|
-
console.log("
|
68
|
+
console.log("Creating all databases except migrations");
|
47
69
|
databasesToEnsure.push(migrationsDatabase);
|
48
70
|
}
|
49
71
|
for (const db of databasesToEnsure) {
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { setupDirsFiles } from "./utils/setupFiles.js";
|
2
|
+
import path from "path";
|
3
|
+
import fs from "fs";
|
4
|
+
export class SetupController {
|
5
|
+
currentDir;
|
6
|
+
constructor(currentDir) {
|
7
|
+
this.currentDir = currentDir;
|
8
|
+
}
|
9
|
+
async runSetup(withExampleData = false) {
|
10
|
+
await setupDirsFiles(withExampleData, this.currentDir);
|
11
|
+
console.log("Setup completed successfully.");
|
12
|
+
}
|
13
|
+
hasExistingConfig() {
|
14
|
+
const configPath = path.join(this.currentDir, "appwrite", "appwriteConfig.ts");
|
15
|
+
return fs.existsSync(configPath);
|
16
|
+
}
|
17
|
+
}
|
@@ -17,24 +17,24 @@ export class SchemaGenerator {
|
|
17
17
|
const collections = this.config.collections;
|
18
18
|
delete this.config.collections;
|
19
19
|
const configPath = path.join(this.appwriteFolderPath, "appwriteConfig.ts");
|
20
|
-
const configContent = `import { type AppwriteConfig } from "appwrite-utils";
|
21
|
-
|
22
|
-
const appwriteConfig: AppwriteConfig = {
|
23
|
-
appwriteEndpoint: "${this.config.appwriteEndpoint}",
|
24
|
-
appwriteProject: "${this.config.appwriteProject}",
|
25
|
-
appwriteKey: "${this.config.appwriteKey}",
|
26
|
-
enableBackups: ${this.config.enableBackups},
|
27
|
-
backupInterval: ${this.config.backupInterval},
|
28
|
-
backupRetention: ${this.config.backupRetention},
|
29
|
-
enableBackupCleanup: ${this.config.enableBackupCleanup},
|
30
|
-
enableMockData: ${this.config.enableMockData},
|
31
|
-
documentBucketId: "${this.config.documentBucketId}",
|
32
|
-
usersCollectionName: "${this.config.usersCollectionName}",
|
33
|
-
databases: ${JSON.stringify(this.config.databases)},
|
34
|
-
buckets: ${JSON.stringify(this.config.buckets)},
|
35
|
-
};
|
36
|
-
|
37
|
-
export default appwriteConfig;
|
20
|
+
const configContent = `import { type AppwriteConfig } from "appwrite-utils";
|
21
|
+
|
22
|
+
const appwriteConfig: AppwriteConfig = {
|
23
|
+
appwriteEndpoint: "${this.config.appwriteEndpoint}",
|
24
|
+
appwriteProject: "${this.config.appwriteProject}",
|
25
|
+
appwriteKey: "${this.config.appwriteKey}",
|
26
|
+
enableBackups: ${this.config.enableBackups},
|
27
|
+
backupInterval: ${this.config.backupInterval},
|
28
|
+
backupRetention: ${this.config.backupRetention},
|
29
|
+
enableBackupCleanup: ${this.config.enableBackupCleanup},
|
30
|
+
enableMockData: ${this.config.enableMockData},
|
31
|
+
documentBucketId: "${this.config.documentBucketId}",
|
32
|
+
usersCollectionName: "${this.config.usersCollectionName}",
|
33
|
+
databases: ${JSON.stringify(this.config.databases)},
|
34
|
+
buckets: ${JSON.stringify(this.config.buckets)},
|
35
|
+
};
|
36
|
+
|
37
|
+
export default appwriteConfig;
|
38
38
|
`;
|
39
39
|
fs.writeFileSync(configPath, configContent, { encoding: "utf-8" });
|
40
40
|
const collectionsFolderPath = path.join(this.appwriteFolderPath, "collections");
|
@@ -44,19 +44,19 @@ export class SchemaGenerator {
|
|
44
44
|
collections?.forEach((collection) => {
|
45
45
|
const { databaseId, ...collectionWithoutDbId } = collection; // Destructure to exclude databaseId
|
46
46
|
const collectionFilePath = path.join(collectionsFolderPath, `${collection.name}.ts`);
|
47
|
-
const collectionContent = `import { type CollectionCreate } from "appwrite-utils";
|
48
|
-
|
49
|
-
const ${collection.name}Config: Partial<CollectionCreate> = {
|
50
|
-
name: "${collection.name}",
|
51
|
-
$id: "${collection.$id}",
|
52
|
-
enabled: ${collection.enabled},
|
53
|
-
documentSecurity: ${collection.documentSecurity},
|
54
|
-
$permissions: [
|
47
|
+
const collectionContent = `import { type CollectionCreate } from "appwrite-utils";
|
48
|
+
|
49
|
+
const ${collection.name}Config: Partial<CollectionCreate> = {
|
50
|
+
name: "${collection.name}",
|
51
|
+
$id: "${collection.$id}",
|
52
|
+
enabled: ${collection.enabled},
|
53
|
+
documentSecurity: ${collection.documentSecurity},
|
54
|
+
$permissions: [
|
55
55
|
${collection.$permissions
|
56
56
|
.map((permission) => `{ permission: "${permission.permission}", target: "${permission.target}" }`)
|
57
|
-
.join(",\n ")}
|
58
|
-
],
|
59
|
-
attributes: [
|
57
|
+
.join(",\n ")}
|
58
|
+
],
|
59
|
+
attributes: [
|
60
60
|
${collection.attributes
|
61
61
|
.map((attr) => {
|
62
62
|
return `{ ${Object.entries(attr)
|
@@ -84,9 +84,9 @@ export class SchemaGenerator {
|
|
84
84
|
})
|
85
85
|
.join(", ")} }`;
|
86
86
|
})
|
87
|
-
.join(",\n ")}
|
88
|
-
],
|
89
|
-
indexes: [
|
87
|
+
.join(",\n ")}
|
88
|
+
],
|
89
|
+
indexes: [
|
90
90
|
${(collection.indexes?.map((index) => {
|
91
91
|
// Map each attribute to ensure it is properly quoted
|
92
92
|
const formattedAttributes = index.attributes.map((attr) => `"${attr}"`).join(", ") ?? "";
|
@@ -94,11 +94,11 @@ export class SchemaGenerator {
|
|
94
94
|
?.filter((order) => order !== null)
|
95
95
|
.map((order) => `"${order}"`)
|
96
96
|
.join(", ") ?? ""}] }`;
|
97
|
-
}) ?? []).join(",\n ")}
|
98
|
-
]
|
99
|
-
};
|
100
|
-
|
101
|
-
export default ${collection.name}Config;
|
97
|
+
}) ?? []).join(",\n ")}
|
98
|
+
]
|
99
|
+
};
|
100
|
+
|
101
|
+
export default ${collection.name}Config;
|
102
102
|
`;
|
103
103
|
fs.writeFileSync(collectionFilePath, collectionContent, {
|
104
104
|
encoding: "utf-8",
|
@@ -1,3 +1,3 @@
|
|
1
1
|
export declare const customDefinitionsFile = "import type { ConverterFunctions, ValidationRules, AfterImportActions } from \"appwrite-utils\";\n\nexport const customConverterFunctions: ConverterFunctions = {\n // Add your custom converter functions here\n}\nexport const customValidationRules: ValidationRules = {\n // Add your custom validation rules here\n}\nexport const customAfterImportActions: AfterImportActions = {\n // Add your custom after import actions here\n}";
|
2
2
|
export declare const createEmptyCollection: (collectionName: string) => void;
|
3
|
-
export declare const setupDirsFiles: (example?: boolean) => Promise<void>;
|
3
|
+
export declare const setupDirsFiles: (example?: boolean, currentDir?: string) => Promise<void>;
|
package/dist/utils/setupFiles.js
CHANGED
@@ -143,8 +143,8 @@ export default ${collectionName};`;
|
|
143
143
|
const collectionFilePath = path.join(collectionsFolder, `${collectionName}.ts`);
|
144
144
|
writeFileSync(collectionFilePath, emptyCollection);
|
145
145
|
};
|
146
|
-
export const setupDirsFiles = async (example = false) => {
|
147
|
-
const basePath = process.cwd();
|
146
|
+
export const setupDirsFiles = async (example = false, currentDir) => {
|
147
|
+
const basePath = currentDir || process.cwd();
|
148
148
|
const srcPath = path.join(basePath);
|
149
149
|
// Check if src directory exists in the current working directory
|
150
150
|
if (!existsSync(srcPath)) {
|
package/dist/utilsController.js
CHANGED
@@ -112,6 +112,8 @@ export class UtilsController {
|
|
112
112
|
if (!this.database || !this.config)
|
113
113
|
throw new Error("Database or config not initialized");
|
114
114
|
for (const database of databases) {
|
115
|
+
if (database.$id === "migrations")
|
116
|
+
continue;
|
115
117
|
await this.createOrUpdateCollections(database);
|
116
118
|
}
|
117
119
|
}
|
package/package.json
CHANGED
@@ -1,53 +1,53 @@
|
|
1
|
-
{
|
2
|
-
"name": "appwrite-utils-cli",
|
3
|
-
"description": "Appwrite Utility Functions to help with database management, data conversion, data import, migrations, and much more. Meant to be used as a CLI tool, I do not recommend installing this in frontend environments.",
|
4
|
-
"version": "0.9.
|
5
|
-
"main": "src/main.ts",
|
6
|
-
"type": "module",
|
7
|
-
"repository": {
|
8
|
-
"type": "git",
|
9
|
-
"url": "https://github.com/zachhandley/AppwriteUtils"
|
10
|
-
},
|
11
|
-
"author": "Zach Handley <zach@blackleafdigital.com> (https://zachhandley.com)",
|
12
|
-
"keywords": [
|
13
|
-
"appwrite",
|
14
|
-
"cli",
|
15
|
-
"utils",
|
16
|
-
"migrations",
|
17
|
-
"data",
|
18
|
-
"database",
|
19
|
-
"import",
|
20
|
-
"migration",
|
21
|
-
"utility"
|
22
|
-
],
|
23
|
-
"bin": {
|
24
|
-
"appwrite-migrate": "./dist/main.js"
|
25
|
-
},
|
26
|
-
"scripts": {
|
27
|
-
"build": "bun run tsc",
|
28
|
-
"start": "tsx --no-cache src/main.ts",
|
29
|
-
"deploy": "bun run build && npm publish --access public",
|
30
|
-
"postinstall": "echo 'This package is intended for CLI use only and should not be added as a dependency in other projects.'"
|
31
|
-
},
|
32
|
-
"dependencies": {
|
33
|
-
"@types/inquirer": "^9.0.7",
|
34
|
-
"appwrite-utils": "^0.3.8",
|
35
|
-
"commander": "^12.1.0",
|
36
|
-
"inquirer": "^9.3.6",
|
37
|
-
"js-yaml": "^4.1.0",
|
38
|
-
"lodash": "^4.17.21",
|
39
|
-
"luxon": "^3.5.0",
|
40
|
-
"nanostores": "^0.10.3",
|
41
|
-
"node-appwrite": "^13.0.0",
|
42
|
-
"tsx": "^4.17.0",
|
43
|
-
"ulidx": "^2.4.0",
|
44
|
-
"winston": "^3.14.1",
|
45
|
-
"zod": "^3.23.8"
|
46
|
-
},
|
47
|
-
"devDependencies": {
|
48
|
-
"@types/js-yaml": "^4.0.9",
|
49
|
-
"@types/lodash": "^4.17.7",
|
50
|
-
"@types/luxon": "^3.4.2",
|
51
|
-
"typescript": "^5.5.4"
|
52
|
-
}
|
53
|
-
}
|
1
|
+
{
|
2
|
+
"name": "appwrite-utils-cli",
|
3
|
+
"description": "Appwrite Utility Functions to help with database management, data conversion, data import, migrations, and much more. Meant to be used as a CLI tool, I do not recommend installing this in frontend environments.",
|
4
|
+
"version": "0.9.4",
|
5
|
+
"main": "src/main.ts",
|
6
|
+
"type": "module",
|
7
|
+
"repository": {
|
8
|
+
"type": "git",
|
9
|
+
"url": "https://github.com/zachhandley/AppwriteUtils"
|
10
|
+
},
|
11
|
+
"author": "Zach Handley <zach@blackleafdigital.com> (https://zachhandley.com)",
|
12
|
+
"keywords": [
|
13
|
+
"appwrite",
|
14
|
+
"cli",
|
15
|
+
"utils",
|
16
|
+
"migrations",
|
17
|
+
"data",
|
18
|
+
"database",
|
19
|
+
"import",
|
20
|
+
"migration",
|
21
|
+
"utility"
|
22
|
+
],
|
23
|
+
"bin": {
|
24
|
+
"appwrite-migrate": "./dist/main.js"
|
25
|
+
},
|
26
|
+
"scripts": {
|
27
|
+
"build": "bun run tsc",
|
28
|
+
"start": "tsx --no-cache src/main.ts",
|
29
|
+
"deploy": "bun run build && npm publish --access public",
|
30
|
+
"postinstall": "echo 'This package is intended for CLI use only and should not be added as a dependency in other projects.'"
|
31
|
+
},
|
32
|
+
"dependencies": {
|
33
|
+
"@types/inquirer": "^9.0.7",
|
34
|
+
"appwrite-utils": "^0.3.8",
|
35
|
+
"commander": "^12.1.0",
|
36
|
+
"inquirer": "^9.3.6",
|
37
|
+
"js-yaml": "^4.1.0",
|
38
|
+
"lodash": "^4.17.21",
|
39
|
+
"luxon": "^3.5.0",
|
40
|
+
"nanostores": "^0.10.3",
|
41
|
+
"node-appwrite": "^13.0.0",
|
42
|
+
"tsx": "^4.17.0",
|
43
|
+
"ulidx": "^2.4.0",
|
44
|
+
"winston": "^3.14.1",
|
45
|
+
"zod": "^3.23.8"
|
46
|
+
},
|
47
|
+
"devDependencies": {
|
48
|
+
"@types/js-yaml": "^4.0.9",
|
49
|
+
"@types/lodash": "^4.17.7",
|
50
|
+
"@types/luxon": "^3.4.2",
|
51
|
+
"typescript": "^5.5.4"
|
52
|
+
}
|
53
|
+
}
|