appwrite-utils-cli 0.9.3 → 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 +1 -0
- package/dist/interactiveCLI.js +10 -46
- package/dist/migrations/setupDatabase.js +28 -6
- package/dist/setupController.d.ts +6 -0
- package/dist/setupController.js +17 -0
- package/dist/utilsController.js +2 -0
- package/package.json +1 -1
- package/src/interactiveCLI.ts +10 -59
- package/src/migrations/setupDatabase.ts +54 -21
- package/src/setupController.ts +25 -0
- package/src/utilsController.ts +1 -0
package/README.md
CHANGED
@@ -124,6 +124,7 @@ This updated CLI ensures that developers have robust tools at their fingertips t
|
|
124
124
|
|
125
125
|
## Changelog
|
126
126
|
|
127
|
+
- 0.9.4: Fixed migrations database ensuring it has the required collections
|
127
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)
|
128
129
|
- 0.9.2: Added changelog back, whoops
|
129
130
|
- 0.0.90: Updated README with new command-line options and fixed alias issues
|
package/dist/interactiveCLI.js
CHANGED
@@ -91,10 +91,6 @@ export class InteractiveCLI {
|
|
91
91
|
}
|
92
92
|
async selectDatabases(databases, message, multiSelect = true) {
|
93
93
|
const choices = databases.map((db) => ({ name: db.name, value: db }));
|
94
|
-
if (multiSelect) {
|
95
|
-
choices.unshift({ name: "Select All", value: "ALL" });
|
96
|
-
choices.push({ name: "Clear Selection", value: "CLEAR" });
|
97
|
-
}
|
98
94
|
const { selectedDatabases } = await inquirer.prompt([
|
99
95
|
{
|
100
96
|
type: multiSelect ? "checkbox" : "list",
|
@@ -105,15 +101,7 @@ export class InteractiveCLI {
|
|
105
101
|
pageSize: 10,
|
106
102
|
},
|
107
103
|
]);
|
108
|
-
|
109
|
-
if (selectedDatabases.includes("ALL")) {
|
110
|
-
return databases;
|
111
|
-
}
|
112
|
-
else if (selectedDatabases.includes("CLEAR")) {
|
113
|
-
return [];
|
114
|
-
}
|
115
|
-
}
|
116
|
-
return selectedDatabases.filter((db) => typeof db !== "string");
|
104
|
+
return selectedDatabases;
|
117
105
|
}
|
118
106
|
async selectCollections(database, databasesClient, message, multiSelect = true) {
|
119
107
|
const collections = await fetchAllCollections(database.$id, databasesClient);
|
@@ -121,10 +109,6 @@ export class InteractiveCLI {
|
|
121
109
|
name: collection.name,
|
122
110
|
value: collection,
|
123
111
|
}));
|
124
|
-
if (multiSelect) {
|
125
|
-
choices.unshift({ name: "Select All", value: "ALL" });
|
126
|
-
choices.push({ name: "Clear Selection", value: "CLEAR" });
|
127
|
-
}
|
128
112
|
const { selectedCollections } = await inquirer.prompt([
|
129
113
|
{
|
130
114
|
type: multiSelect ? "checkbox" : "list",
|
@@ -135,25 +119,13 @@ export class InteractiveCLI {
|
|
135
119
|
pageSize: 10,
|
136
120
|
},
|
137
121
|
]);
|
138
|
-
|
139
|
-
if (selectedCollections.includes("ALL")) {
|
140
|
-
return collections;
|
141
|
-
}
|
142
|
-
else if (selectedCollections.includes("CLEAR")) {
|
143
|
-
return [];
|
144
|
-
}
|
145
|
-
}
|
146
|
-
return selectedCollections.filter((collection) => typeof collection !== "string");
|
122
|
+
return selectedCollections;
|
147
123
|
}
|
148
124
|
async selectBuckets(buckets, message, multiSelect = true) {
|
149
125
|
const choices = buckets.map((bucket) => ({
|
150
126
|
name: bucket.name,
|
151
|
-
value: bucket
|
127
|
+
value: bucket,
|
152
128
|
}));
|
153
|
-
if (multiSelect) {
|
154
|
-
choices.unshift({ name: "Select All", value: "ALL" });
|
155
|
-
choices.push({ name: "Clear Selection", value: "CLEAR" });
|
156
|
-
}
|
157
129
|
const { selectedBuckets } = await inquirer.prompt([
|
158
130
|
{
|
159
131
|
type: multiSelect ? "checkbox" : "list",
|
@@ -164,15 +136,7 @@ export class InteractiveCLI {
|
|
164
136
|
pageSize: 10,
|
165
137
|
},
|
166
138
|
]);
|
167
|
-
|
168
|
-
if (selectedBuckets.includes("ALL")) {
|
169
|
-
return buckets;
|
170
|
-
}
|
171
|
-
else if (selectedBuckets.includes("CLEAR")) {
|
172
|
-
return [];
|
173
|
-
}
|
174
|
-
}
|
175
|
-
return selectedBuckets.map((id) => buckets.find((bucket) => bucket.$id === id));
|
139
|
+
return selectedBuckets;
|
176
140
|
}
|
177
141
|
async createCollectionConfig() {
|
178
142
|
const { collectionName } = await inquirer.prompt([
|
@@ -365,7 +329,7 @@ export class InteractiveCLI {
|
|
365
329
|
throw new Error("Database is not initialized. Is the config file correct and created?");
|
366
330
|
}
|
367
331
|
const databases = await fetchAllDatabases(this.controller.database);
|
368
|
-
const selectedDatabases = await this.selectDatabases(databases, "Select databases to synchronize
|
332
|
+
const selectedDatabases = await this.selectDatabases(databases, "Select databases to synchronize:");
|
369
333
|
console.log("Configuring storage buckets...");
|
370
334
|
const updatedConfig = await this.configureBuckets(this.controller.config, selectedDatabases);
|
371
335
|
console.log("Synchronizing configurations...");
|
@@ -376,7 +340,7 @@ export class InteractiveCLI {
|
|
376
340
|
throw new Error("Database is not initialized, is the config file correct & created?");
|
377
341
|
}
|
378
342
|
const databases = await fetchAllDatabases(this.controller.database);
|
379
|
-
const selectedDatabases = await this.selectDatabases(databases, "Select databases to backup
|
343
|
+
const selectedDatabases = await this.selectDatabases(databases, "Select databases to backup:");
|
380
344
|
for (const db of selectedDatabases) {
|
381
345
|
console.log(`Backing up database: ${db.name}`);
|
382
346
|
await this.controller.backupDatabase(db);
|
@@ -388,12 +352,12 @@ export class InteractiveCLI {
|
|
388
352
|
}
|
389
353
|
const databases = await fetchAllDatabases(this.controller.database);
|
390
354
|
const storage = await listBuckets(this.controller.storage);
|
391
|
-
const selectedDatabases = await this.selectDatabases(databases, "Select databases to wipe
|
355
|
+
const selectedDatabases = await this.selectDatabases(databases, "Select databases to wipe:");
|
392
356
|
const { selectedStorage } = await inquirer.prompt([
|
393
357
|
{
|
394
358
|
type: "checkbox",
|
395
359
|
name: "selectedStorage",
|
396
|
-
message: "Select storage buckets to wipe
|
360
|
+
message: "Select storage buckets to wipe:",
|
397
361
|
choices: storage.buckets.map((s) => ({ name: s.name, value: s.$id })),
|
398
362
|
},
|
399
363
|
]);
|
@@ -441,7 +405,7 @@ export class InteractiveCLI {
|
|
441
405
|
const selectedDatabases = await this.selectDatabases(databases, "Select the database(s) to import data into:");
|
442
406
|
let selectedCollections = [];
|
443
407
|
for (const db of selectedDatabases) {
|
444
|
-
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);
|
445
409
|
selectedCollections = [...selectedCollections, ...dbCollections];
|
446
410
|
}
|
447
411
|
const { shouldWriteFile } = await inquirer.prompt([
|
@@ -516,7 +480,7 @@ export class InteractiveCLI {
|
|
516
480
|
}
|
517
481
|
const [fromDb] = await this.selectDatabases(sourceDatabases, "Select the source database:", false);
|
518
482
|
const [targetDb] = await this.selectDatabases(targetDatabases.filter((db) => db.$id !== fromDb.$id), "Select the target database:", false);
|
519
|
-
const selectedCollections = await this.selectCollections(fromDb, sourceClient, "Select collections to transfer
|
483
|
+
const selectedCollections = await this.selectCollections(fromDb, sourceClient, "Select collections to transfer):");
|
520
484
|
const { transferStorage } = await inquirer.prompt([
|
521
485
|
{
|
522
486
|
type: "confirm",
|
@@ -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,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
|
+
}
|
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,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "appwrite-utils-cli",
|
3
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
|
+
"version": "0.9.4",
|
5
5
|
"main": "src/main.ts",
|
6
6
|
"type": "module",
|
7
7
|
"repository": {
|
package/src/interactiveCLI.ts
CHANGED
@@ -110,11 +110,6 @@ export class InteractiveCLI {
|
|
110
110
|
): Promise<Models.Database[]> {
|
111
111
|
const choices = databases.map((db) => ({ name: db.name, value: db }));
|
112
112
|
|
113
|
-
if (multiSelect) {
|
114
|
-
choices.unshift({ name: "Select All", value: "ALL" as any });
|
115
|
-
choices.push({ name: "Clear Selection", value: "CLEAR" as any });
|
116
|
-
}
|
117
|
-
|
118
113
|
const { selectedDatabases } = await inquirer.prompt([
|
119
114
|
{
|
120
115
|
type: multiSelect ? "checkbox" : "list",
|
@@ -126,18 +121,7 @@ export class InteractiveCLI {
|
|
126
121
|
},
|
127
122
|
]);
|
128
123
|
|
129
|
-
|
130
|
-
if (selectedDatabases.includes("ALL")) {
|
131
|
-
return databases;
|
132
|
-
} else if (selectedDatabases.includes("CLEAR")) {
|
133
|
-
return [];
|
134
|
-
}
|
135
|
-
}
|
136
|
-
|
137
|
-
return selectedDatabases.filter(
|
138
|
-
(db: Models.Database | string): db is Models.Database =>
|
139
|
-
typeof db !== "string"
|
140
|
-
);
|
124
|
+
return selectedDatabases;
|
141
125
|
}
|
142
126
|
|
143
127
|
private async selectCollections(
|
@@ -155,11 +139,6 @@ export class InteractiveCLI {
|
|
155
139
|
value: collection,
|
156
140
|
}));
|
157
141
|
|
158
|
-
if (multiSelect) {
|
159
|
-
choices.unshift({ name: "Select All", value: "ALL" as any });
|
160
|
-
choices.push({ name: "Clear Selection", value: "CLEAR" as any });
|
161
|
-
}
|
162
|
-
|
163
142
|
const { selectedCollections } = await inquirer.prompt([
|
164
143
|
{
|
165
144
|
type: multiSelect ? "checkbox" : "list",
|
@@ -171,19 +150,7 @@ export class InteractiveCLI {
|
|
171
150
|
},
|
172
151
|
]);
|
173
152
|
|
174
|
-
|
175
|
-
if (selectedCollections.includes("ALL")) {
|
176
|
-
return collections;
|
177
|
-
} else if (selectedCollections.includes("CLEAR")) {
|
178
|
-
return [];
|
179
|
-
}
|
180
|
-
}
|
181
|
-
|
182
|
-
return selectedCollections.filter(
|
183
|
-
(
|
184
|
-
collection: Models.Collection | string
|
185
|
-
): collection is Models.Collection => typeof collection !== "string"
|
186
|
-
);
|
153
|
+
return selectedCollections;
|
187
154
|
}
|
188
155
|
|
189
156
|
private async selectBuckets(
|
@@ -193,14 +160,9 @@ export class InteractiveCLI {
|
|
193
160
|
): Promise<Models.Bucket[]> {
|
194
161
|
const choices = buckets.map((bucket) => ({
|
195
162
|
name: bucket.name,
|
196
|
-
value: bucket
|
163
|
+
value: bucket,
|
197
164
|
}));
|
198
165
|
|
199
|
-
if (multiSelect) {
|
200
|
-
choices.unshift({ name: "Select All", value: "ALL" });
|
201
|
-
choices.push({ name: "Clear Selection", value: "CLEAR" });
|
202
|
-
}
|
203
|
-
|
204
166
|
const { selectedBuckets } = await inquirer.prompt([
|
205
167
|
{
|
206
168
|
type: multiSelect ? "checkbox" : "list",
|
@@ -212,17 +174,7 @@ export class InteractiveCLI {
|
|
212
174
|
},
|
213
175
|
]);
|
214
176
|
|
215
|
-
|
216
|
-
if (selectedBuckets.includes("ALL")) {
|
217
|
-
return buckets;
|
218
|
-
} else if (selectedBuckets.includes("CLEAR")) {
|
219
|
-
return [];
|
220
|
-
}
|
221
|
-
}
|
222
|
-
|
223
|
-
return selectedBuckets.map(
|
224
|
-
(id: string) => buckets.find((bucket) => bucket.$id === id)!
|
225
|
-
);
|
177
|
+
return selectedBuckets;
|
226
178
|
}
|
227
179
|
|
228
180
|
private async createCollectionConfig(): Promise<void> {
|
@@ -475,7 +427,7 @@ export class InteractiveCLI {
|
|
475
427
|
|
476
428
|
const selectedDatabases = await this.selectDatabases(
|
477
429
|
databases,
|
478
|
-
"Select databases to synchronize
|
430
|
+
"Select databases to synchronize:"
|
479
431
|
);
|
480
432
|
|
481
433
|
console.log("Configuring storage buckets...");
|
@@ -501,7 +453,7 @@ export class InteractiveCLI {
|
|
501
453
|
|
502
454
|
const selectedDatabases = await this.selectDatabases(
|
503
455
|
databases,
|
504
|
-
"Select databases to backup
|
456
|
+
"Select databases to backup:"
|
505
457
|
);
|
506
458
|
|
507
459
|
for (const db of selectedDatabases) {
|
@@ -521,15 +473,14 @@ export class InteractiveCLI {
|
|
521
473
|
|
522
474
|
const selectedDatabases = await this.selectDatabases(
|
523
475
|
databases,
|
524
|
-
"Select databases to wipe
|
476
|
+
"Select databases to wipe:"
|
525
477
|
);
|
526
478
|
|
527
479
|
const { selectedStorage } = await inquirer.prompt([
|
528
480
|
{
|
529
481
|
type: "checkbox",
|
530
482
|
name: "selectedStorage",
|
531
|
-
message:
|
532
|
-
"Select storage buckets to wipe (or select none to skip storage wipe):",
|
483
|
+
message: "Select storage buckets to wipe:",
|
533
484
|
choices: storage.buckets.map((s) => ({ name: s.name, value: s.$id })),
|
534
485
|
},
|
535
486
|
]);
|
@@ -592,7 +543,7 @@ export class InteractiveCLI {
|
|
592
543
|
const dbCollections = await this.selectCollections(
|
593
544
|
db,
|
594
545
|
this.controller!.database,
|
595
|
-
`Select collections to import data into for database ${db.name}
|
546
|
+
`Select collections to import data into for database ${db.name}:`,
|
596
547
|
true
|
597
548
|
);
|
598
549
|
selectedCollections = [...selectedCollections, ...dbCollections];
|
@@ -703,7 +654,7 @@ export class InteractiveCLI {
|
|
703
654
|
const selectedCollections = await this.selectCollections(
|
704
655
|
fromDb,
|
705
656
|
sourceClient,
|
706
|
-
"Select collections to transfer
|
657
|
+
"Select collections to transfer):"
|
707
658
|
);
|
708
659
|
|
709
660
|
const { transferStorage } = await inquirer.prompt([
|
@@ -14,7 +14,7 @@ export const setupMigrationDatabase = async (config: AppwriteConfig) => {
|
|
14
14
|
console.log("Starting Migrations Setup");
|
15
15
|
console.log("---------------------------------");
|
16
16
|
const database = new Databases(config.appwriteClient!);
|
17
|
-
let db: Models.Database |
|
17
|
+
let db: Models.Database | undefined;
|
18
18
|
const migrationCollectionsSetup = getMigrationCollectionSchemas();
|
19
19
|
|
20
20
|
try {
|
@@ -31,36 +31,69 @@ export const setupMigrationDatabase = async (config: AppwriteConfig) => {
|
|
31
31
|
console.log("Migrations database created");
|
32
32
|
}
|
33
33
|
|
34
|
+
if (!db) {
|
35
|
+
console.error("Failed to create or retrieve the migrations database");
|
36
|
+
return;
|
37
|
+
}
|
38
|
+
|
34
39
|
for (const [collectionName, { collection, attributes }] of Object.entries(
|
35
40
|
migrationCollectionsSetup
|
36
41
|
)) {
|
37
42
|
const collectionId = toCamelCase(collectionName);
|
38
|
-
let collectionFound: Models.Collection |
|
43
|
+
let collectionFound: Models.Collection | undefined;
|
39
44
|
try {
|
40
45
|
collectionFound = await tryAwaitWithRetry(
|
41
|
-
async () => await database.getCollection(db
|
46
|
+
async () => await database.getCollection(db.$id, collectionId),
|
47
|
+
undefined,
|
48
|
+
true
|
42
49
|
);
|
50
|
+
console.log(`Collection found: ${collectionId}`);
|
43
51
|
} catch (e) {
|
44
52
|
console.log(`Collection not found: ${collectionId}`);
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
try {
|
54
|
+
collectionFound = await tryAwaitWithRetry(
|
55
|
+
async () =>
|
56
|
+
await database.createCollection(
|
57
|
+
db.$id,
|
58
|
+
collectionId,
|
59
|
+
collectionName,
|
60
|
+
undefined,
|
61
|
+
collection.documentSecurity,
|
62
|
+
collection.enabled
|
63
|
+
),
|
64
|
+
undefined,
|
65
|
+
true
|
66
|
+
);
|
67
|
+
console.log(`Collection created: ${collectionId}`);
|
68
|
+
} catch (createError) {
|
69
|
+
console.error(
|
70
|
+
`Failed to create collection: ${collectionId}`,
|
71
|
+
createError
|
72
|
+
);
|
73
|
+
continue;
|
74
|
+
}
|
56
75
|
}
|
76
|
+
|
77
|
+
if (!collectionFound) {
|
78
|
+
console.error(`Failed to create or retrieve collection: ${collectionId}`);
|
79
|
+
continue;
|
80
|
+
}
|
81
|
+
|
57
82
|
for (const attribute of attributes) {
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
83
|
+
try {
|
84
|
+
await createOrUpdateAttribute(
|
85
|
+
database,
|
86
|
+
db.$id,
|
87
|
+
collectionFound,
|
88
|
+
attribute
|
89
|
+
);
|
90
|
+
console.log(`Attribute created/updated: ${attribute.key}`);
|
91
|
+
} catch (attrError) {
|
92
|
+
console.error(
|
93
|
+
`Failed to create/update attribute: ${attribute.key}`,
|
94
|
+
attrError
|
95
|
+
);
|
96
|
+
}
|
64
97
|
}
|
65
98
|
}
|
66
99
|
console.log("---------------------------------");
|
@@ -80,7 +113,7 @@ export const ensureDatabasesExist = async (config: AppwriteConfig) => {
|
|
80
113
|
(d) => d.name.toLowerCase().trim().replace(" ", "") === "migrations"
|
81
114
|
);
|
82
115
|
if (existingDatabases.databases.length !== 0 && migrationsDatabase) {
|
83
|
-
console.log("
|
116
|
+
console.log("Creating all databases except migrations");
|
84
117
|
databasesToEnsure.push(migrationsDatabase);
|
85
118
|
}
|
86
119
|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import { setupDirsFiles } from "./utils/setupFiles.js";
|
2
|
+
import path from "path";
|
3
|
+
import fs from "fs";
|
4
|
+
|
5
|
+
export class SetupController {
|
6
|
+
private currentDir: string;
|
7
|
+
|
8
|
+
constructor(currentDir: string) {
|
9
|
+
this.currentDir = currentDir;
|
10
|
+
}
|
11
|
+
|
12
|
+
async runSetup(withExampleData: boolean = false): Promise<void> {
|
13
|
+
await setupDirsFiles(withExampleData, this.currentDir);
|
14
|
+
console.log("Setup completed successfully.");
|
15
|
+
}
|
16
|
+
|
17
|
+
hasExistingConfig(): boolean {
|
18
|
+
const configPath = path.join(
|
19
|
+
this.currentDir,
|
20
|
+
"appwrite",
|
21
|
+
"appwriteConfig.ts"
|
22
|
+
);
|
23
|
+
return fs.existsSync(configPath);
|
24
|
+
}
|
25
|
+
}
|
package/src/utilsController.ts
CHANGED
@@ -161,6 +161,7 @@ export class UtilsController {
|
|
161
161
|
if (!this.database || !this.config)
|
162
162
|
throw new Error("Database or config not initialized");
|
163
163
|
for (const database of databases) {
|
164
|
+
if (database.$id === "migrations") continue;
|
164
165
|
await this.createOrUpdateCollections(database);
|
165
166
|
}
|
166
167
|
}
|