appwrite-utils-cli 0.0.285 → 0.9.0
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 +122 -96
- package/dist/collections/attributes.d.ts +4 -0
- package/dist/collections/attributes.js +224 -0
- package/dist/collections/indexes.d.ts +4 -0
- package/dist/collections/indexes.js +27 -0
- package/dist/collections/methods.d.ts +16 -0
- package/dist/collections/methods.js +216 -0
- package/dist/databases/methods.d.ts +6 -0
- package/dist/databases/methods.js +33 -0
- package/dist/interactiveCLI.d.ts +19 -0
- package/dist/interactiveCLI.js +555 -0
- package/dist/main.js +227 -62
- package/dist/migrations/afterImportActions.js +37 -40
- package/dist/migrations/appwriteToX.d.ts +26 -25
- package/dist/migrations/appwriteToX.js +42 -6
- package/dist/migrations/attributes.js +21 -20
- package/dist/migrations/backup.d.ts +93 -87
- package/dist/migrations/collections.d.ts +6 -0
- package/dist/migrations/collections.js +149 -20
- package/dist/migrations/converters.d.ts +2 -18
- package/dist/migrations/converters.js +13 -2
- package/dist/migrations/dataLoader.d.ts +276 -161
- package/dist/migrations/dataLoader.js +535 -292
- package/dist/migrations/databases.js +8 -2
- package/dist/migrations/helper.d.ts +3 -0
- package/dist/migrations/helper.js +21 -0
- package/dist/migrations/importController.d.ts +5 -2
- package/dist/migrations/importController.js +125 -88
- package/dist/migrations/importDataActions.d.ts +9 -1
- package/dist/migrations/importDataActions.js +15 -3
- package/dist/migrations/indexes.js +3 -2
- package/dist/migrations/logging.js +20 -8
- package/dist/migrations/migrationHelper.d.ts +9 -4
- package/dist/migrations/migrationHelper.js +6 -5
- package/dist/migrations/openapi.d.ts +1 -1
- package/dist/migrations/openapi.js +33 -18
- package/dist/migrations/queue.js +3 -2
- package/dist/migrations/relationships.d.ts +2 -2
- package/dist/migrations/schemaStrings.js +53 -41
- package/dist/migrations/setupDatabase.d.ts +2 -4
- package/dist/migrations/setupDatabase.js +24 -105
- package/dist/migrations/storage.d.ts +3 -1
- package/dist/migrations/storage.js +110 -16
- package/dist/migrations/transfer.d.ts +30 -0
- package/dist/migrations/transfer.js +337 -0
- package/dist/migrations/users.d.ts +2 -1
- package/dist/migrations/users.js +78 -43
- package/dist/schemas/authUser.d.ts +2 -2
- package/dist/storage/methods.d.ts +15 -0
- package/dist/storage/methods.js +207 -0
- package/dist/storage/schemas.d.ts +687 -0
- package/dist/storage/schemas.js +175 -0
- package/dist/utils/getClientFromConfig.d.ts +4 -0
- package/dist/utils/getClientFromConfig.js +16 -0
- package/dist/utils/helperFunctions.d.ts +11 -1
- package/dist/utils/helperFunctions.js +38 -0
- package/dist/utils/retryFailedPromises.d.ts +2 -0
- package/dist/utils/retryFailedPromises.js +21 -0
- package/dist/utils/schemaStrings.d.ts +13 -0
- package/dist/utils/schemaStrings.js +403 -0
- package/dist/utils/setupFiles.js +110 -61
- package/dist/utilsController.d.ts +40 -22
- package/dist/utilsController.js +164 -84
- package/package.json +13 -15
- package/src/collections/attributes.ts +483 -0
- package/src/collections/indexes.ts +53 -0
- package/src/collections/methods.ts +331 -0
- package/src/databases/methods.ts +47 -0
- package/src/init.ts +64 -64
- package/src/interactiveCLI.ts +767 -0
- package/src/main.ts +292 -83
- package/src/migrations/afterImportActions.ts +553 -490
- package/src/migrations/appwriteToX.ts +237 -174
- package/src/migrations/attributes.ts +483 -422
- package/src/migrations/backup.ts +205 -205
- package/src/migrations/collections.ts +545 -300
- package/src/migrations/converters.ts +161 -150
- package/src/migrations/dataLoader.ts +1615 -1304
- package/src/migrations/databases.ts +44 -25
- package/src/migrations/dbHelpers.ts +92 -92
- package/src/migrations/helper.ts +40 -0
- package/src/migrations/importController.ts +448 -384
- package/src/migrations/importDataActions.ts +315 -307
- package/src/migrations/indexes.ts +40 -37
- package/src/migrations/logging.ts +29 -16
- package/src/migrations/migrationHelper.ts +207 -201
- package/src/migrations/openapi.ts +83 -70
- package/src/migrations/queue.ts +118 -119
- package/src/migrations/relationships.ts +324 -324
- package/src/migrations/schemaStrings.ts +472 -460
- package/src/migrations/setupDatabase.ts +118 -219
- package/src/migrations/storage.ts +538 -358
- package/src/migrations/transfer.ts +608 -0
- package/src/migrations/users.ts +362 -285
- package/src/migrations/validationRules.ts +63 -63
- package/src/schemas/authUser.ts +23 -23
- package/src/setup.ts +8 -8
- package/src/storage/methods.ts +371 -0
- package/src/storage/schemas.ts +205 -0
- package/src/types.ts +9 -9
- package/src/utils/getClientFromConfig.ts +17 -0
- package/src/utils/helperFunctions.ts +181 -127
- package/src/utils/index.ts +2 -2
- package/src/utils/loadConfigs.ts +59 -59
- package/src/utils/retryFailedPromises.ts +27 -0
- package/src/utils/schemaStrings.ts +473 -0
- package/src/utils/setupFiles.ts +228 -182
- package/src/utilsController.ts +325 -194
- package/tsconfig.json +37 -37
@@ -0,0 +1,331 @@
|
|
1
|
+
import {
|
2
|
+
Client,
|
3
|
+
Databases,
|
4
|
+
ID,
|
5
|
+
Permission,
|
6
|
+
Query,
|
7
|
+
type Models,
|
8
|
+
} from "node-appwrite";
|
9
|
+
import type { AppwriteConfig, CollectionCreate } from "appwrite-utils";
|
10
|
+
import { nameToIdMapping, processQueue } from "../migrations/queue.js";
|
11
|
+
import { createUpdateCollectionAttributes } from "./attributes.js";
|
12
|
+
import { createOrUpdateIndexes } from "./indexes.js";
|
13
|
+
import _ from "lodash";
|
14
|
+
import { SchemaGenerator } from "../utils/schemaStrings.js";
|
15
|
+
import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
|
16
|
+
|
17
|
+
export const documentExists = async (
|
18
|
+
db: Databases,
|
19
|
+
dbId: string,
|
20
|
+
targetCollectionId: string,
|
21
|
+
toCreateObject: any
|
22
|
+
): Promise<Models.Document | null> => {
|
23
|
+
// Had to do this because kept running into issues with type checking arrays so, sorry 40ms
|
24
|
+
const collection = await db.getCollection(dbId, targetCollectionId);
|
25
|
+
const attributes = collection.attributes as any[];
|
26
|
+
let arrayTypeAttributes = attributes
|
27
|
+
.filter((attribute: any) => attribute.array === true)
|
28
|
+
.map((attribute: any) => attribute.key);
|
29
|
+
// Function to check if a string is JSON
|
30
|
+
const isJsonString = (str: string) => {
|
31
|
+
try {
|
32
|
+
const json = JSON.parse(str);
|
33
|
+
return typeof json === "object" && json !== null; // Check if parsed JSON is an object or array
|
34
|
+
} catch (e) {
|
35
|
+
return false;
|
36
|
+
}
|
37
|
+
};
|
38
|
+
|
39
|
+
// Validate and prepare query parameters
|
40
|
+
const validQueryParams = _.chain(toCreateObject)
|
41
|
+
.pickBy(
|
42
|
+
(value, key) =>
|
43
|
+
!arrayTypeAttributes.includes(key) &&
|
44
|
+
!key.startsWith("$") &&
|
45
|
+
!_.isNull(value) &&
|
46
|
+
!_.isUndefined(value) &&
|
47
|
+
!_.isEmpty(value) &&
|
48
|
+
!_.isObject(value) && // Keeps excluding objects
|
49
|
+
!_.isArray(value) && // Explicitly exclude arrays
|
50
|
+
!(_.isString(value) && isJsonString(value)) && // Exclude JSON strings
|
51
|
+
(_.isString(value) ? value.length < 4096 && value.length > 0 : true) // String length check
|
52
|
+
)
|
53
|
+
.mapValues((value, key) =>
|
54
|
+
_.isString(value) || _.isNumber(value) || _.isBoolean(value)
|
55
|
+
? value
|
56
|
+
: null
|
57
|
+
)
|
58
|
+
.omitBy(_.isNull) // Remove any null values that might have been added in mapValues
|
59
|
+
.toPairs()
|
60
|
+
.slice(0, 25) // Limit to 25 to adhere to query limit
|
61
|
+
.map(([key, value]) => Query.equal(key, value as any))
|
62
|
+
.value();
|
63
|
+
|
64
|
+
// Execute the query with the validated and prepared parameters
|
65
|
+
const result = await db.listDocuments(
|
66
|
+
dbId,
|
67
|
+
targetCollectionId,
|
68
|
+
validQueryParams
|
69
|
+
);
|
70
|
+
return result.documents[0] || null;
|
71
|
+
};
|
72
|
+
|
73
|
+
export const checkForCollection = async (
|
74
|
+
db: Databases,
|
75
|
+
dbId: string,
|
76
|
+
collection: Partial<CollectionCreate>
|
77
|
+
): Promise<Models.Collection | null> => {
|
78
|
+
try {
|
79
|
+
console.log(`Checking for collection with name: ${collection.name}`);
|
80
|
+
const response = await tryAwaitWithRetry(
|
81
|
+
async () =>
|
82
|
+
await db.listCollections(dbId, [Query.equal("name", collection.name!)])
|
83
|
+
);
|
84
|
+
if (response.collections.length > 0) {
|
85
|
+
console.log(`Collection found: ${response.collections[0].$id}`);
|
86
|
+
return { ...collection, ...response.collections[0] };
|
87
|
+
} else {
|
88
|
+
console.log(`No collection found with name: ${collection.name}`);
|
89
|
+
return null;
|
90
|
+
}
|
91
|
+
} catch (error) {
|
92
|
+
console.error(`Error checking for collection: ${error}`);
|
93
|
+
return null;
|
94
|
+
}
|
95
|
+
};
|
96
|
+
|
97
|
+
// Helper function to fetch and cache collection by name
|
98
|
+
export const fetchAndCacheCollectionByName = async (
|
99
|
+
db: Databases,
|
100
|
+
dbId: string,
|
101
|
+
collectionName: string
|
102
|
+
): Promise<Models.Collection | undefined> => {
|
103
|
+
if (nameToIdMapping.has(collectionName)) {
|
104
|
+
const collectionId = nameToIdMapping.get(collectionName);
|
105
|
+
console.log(`\tCollection found in cache: ${collectionId}`);
|
106
|
+
return await tryAwaitWithRetry(
|
107
|
+
async () => await db.getCollection(dbId, collectionId!)
|
108
|
+
);
|
109
|
+
} else {
|
110
|
+
console.log(`\tFetching collection by name: ${collectionName}`);
|
111
|
+
const collectionsPulled = await tryAwaitWithRetry(
|
112
|
+
async () =>
|
113
|
+
await db.listCollections(dbId, [Query.equal("name", collectionName)])
|
114
|
+
);
|
115
|
+
if (collectionsPulled.total > 0) {
|
116
|
+
const collection = collectionsPulled.collections[0];
|
117
|
+
console.log(`\tCollection found: ${collection.$id}`);
|
118
|
+
nameToIdMapping.set(collectionName, collection.$id);
|
119
|
+
return collection;
|
120
|
+
} else {
|
121
|
+
console.log(`\tCollection not found by name: ${collectionName}`);
|
122
|
+
return undefined;
|
123
|
+
}
|
124
|
+
}
|
125
|
+
};
|
126
|
+
|
127
|
+
export const wipeDatabase = async (
|
128
|
+
database: Databases,
|
129
|
+
databaseId: string
|
130
|
+
): Promise<{ collectionId: string; collectionName: string }[]> => {
|
131
|
+
console.log(`Wiping database: ${databaseId}`);
|
132
|
+
const existingCollections = await fetchAllCollections(databaseId, database);
|
133
|
+
let collectionsDeleted: { collectionId: string; collectionName: string }[] =
|
134
|
+
[];
|
135
|
+
for (const { $id: collectionId, name: name } of existingCollections) {
|
136
|
+
console.log(`Deleting collection: ${collectionId}`);
|
137
|
+
collectionsDeleted.push({
|
138
|
+
collectionId: collectionId,
|
139
|
+
collectionName: name,
|
140
|
+
});
|
141
|
+
tryAwaitWithRetry(
|
142
|
+
async () => await database.deleteCollection(databaseId, collectionId)
|
143
|
+
); // Try to delete the collection and ignore errors if it doesn't exist or if it's already being deleted
|
144
|
+
}
|
145
|
+
return collectionsDeleted;
|
146
|
+
};
|
147
|
+
|
148
|
+
export const generateSchemas = async (
|
149
|
+
config: AppwriteConfig,
|
150
|
+
appwriteFolderPath: string
|
151
|
+
): Promise<void> => {
|
152
|
+
const schemaGenerator = new SchemaGenerator(config, appwriteFolderPath);
|
153
|
+
schemaGenerator.generateSchemas();
|
154
|
+
};
|
155
|
+
|
156
|
+
export const createOrUpdateCollections = async (
|
157
|
+
database: Databases,
|
158
|
+
databaseId: string,
|
159
|
+
config: AppwriteConfig,
|
160
|
+
deletedCollections?: { collectionId: string; collectionName: string }[]
|
161
|
+
): Promise<void> => {
|
162
|
+
const configCollections = config.collections;
|
163
|
+
if (!configCollections) {
|
164
|
+
return;
|
165
|
+
}
|
166
|
+
const usedIds = new Set(); // To track IDs used in this operation
|
167
|
+
|
168
|
+
for (const { attributes, indexes, ...collection } of configCollections) {
|
169
|
+
// Prepare permissions for the collection
|
170
|
+
const permissions: string[] = [];
|
171
|
+
if (collection.$permissions && collection.$permissions.length > 0) {
|
172
|
+
for (const permission of collection.$permissions) {
|
173
|
+
switch (permission.permission) {
|
174
|
+
case "read":
|
175
|
+
permissions.push(Permission.read(permission.target));
|
176
|
+
break;
|
177
|
+
case "create":
|
178
|
+
permissions.push(Permission.create(permission.target));
|
179
|
+
break;
|
180
|
+
case "update":
|
181
|
+
permissions.push(Permission.update(permission.target));
|
182
|
+
break;
|
183
|
+
case "delete":
|
184
|
+
permissions.push(Permission.delete(permission.target));
|
185
|
+
break;
|
186
|
+
case "write":
|
187
|
+
permissions.push(Permission.write(permission.target));
|
188
|
+
break;
|
189
|
+
default:
|
190
|
+
console.log(`Unknown permission: ${permission.permission}`);
|
191
|
+
break;
|
192
|
+
}
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
// Check if the collection already exists by name
|
197
|
+
let collectionsFound = await tryAwaitWithRetry(
|
198
|
+
async () =>
|
199
|
+
await database.listCollections(databaseId, [
|
200
|
+
Query.equal("name", collection.name),
|
201
|
+
])
|
202
|
+
);
|
203
|
+
|
204
|
+
let collectionToUse =
|
205
|
+
collectionsFound.total > 0 ? collectionsFound.collections[0] : null;
|
206
|
+
|
207
|
+
// Determine the correct ID for the collection
|
208
|
+
let collectionId: string;
|
209
|
+
if (!collectionToUse) {
|
210
|
+
console.log(`Creating collection: ${collection.name}`);
|
211
|
+
let foundColl = deletedCollections?.find(
|
212
|
+
(coll) =>
|
213
|
+
coll.collectionName.toLowerCase().trim().replace(" ", "") ===
|
214
|
+
collection.name.toLowerCase().trim().replace(" ", "")
|
215
|
+
);
|
216
|
+
|
217
|
+
if (collection.$id) {
|
218
|
+
collectionId = collection.$id; // Always use the provided $id if present
|
219
|
+
} else if (foundColl && !usedIds.has(foundColl.collectionId)) {
|
220
|
+
collectionId = foundColl.collectionId; // Use ID from deleted collection if not already used
|
221
|
+
} else {
|
222
|
+
collectionId = ID.unique(); // Generate a new unique ID
|
223
|
+
}
|
224
|
+
|
225
|
+
usedIds.add(collectionId); // Mark this ID as used
|
226
|
+
|
227
|
+
// Create the collection with the determined ID
|
228
|
+
try {
|
229
|
+
collectionToUse = await tryAwaitWithRetry(
|
230
|
+
async () =>
|
231
|
+
await database.createCollection(
|
232
|
+
databaseId,
|
233
|
+
collectionId,
|
234
|
+
collection.name,
|
235
|
+
permissions,
|
236
|
+
collection.documentSecurity ?? false,
|
237
|
+
collection.enabled ?? true
|
238
|
+
)
|
239
|
+
);
|
240
|
+
collection.$id = collectionToUse!.$id;
|
241
|
+
nameToIdMapping.set(collection.name, collectionToUse!.$id);
|
242
|
+
} catch (error) {
|
243
|
+
console.error(
|
244
|
+
`Failed to create collection ${collection.name} with ID ${collectionId}: ${error}`
|
245
|
+
);
|
246
|
+
continue; // Skip to the next collection on failure
|
247
|
+
}
|
248
|
+
} else {
|
249
|
+
console.log(`Collection ${collection.name} exists, updating it`);
|
250
|
+
await tryAwaitWithRetry(
|
251
|
+
async () =>
|
252
|
+
await database.updateCollection(
|
253
|
+
databaseId,
|
254
|
+
collectionToUse!.$id,
|
255
|
+
collection.name,
|
256
|
+
permissions,
|
257
|
+
collection.documentSecurity ?? false,
|
258
|
+
collection.enabled ?? true
|
259
|
+
)
|
260
|
+
);
|
261
|
+
}
|
262
|
+
|
263
|
+
// Update attributes and indexes for the collection
|
264
|
+
console.log("Creating Attributes");
|
265
|
+
await createUpdateCollectionAttributes(
|
266
|
+
database,
|
267
|
+
databaseId,
|
268
|
+
collectionToUse!,
|
269
|
+
attributes
|
270
|
+
);
|
271
|
+
console.log("Creating Indexes");
|
272
|
+
await createOrUpdateIndexes(
|
273
|
+
databaseId,
|
274
|
+
database,
|
275
|
+
collectionToUse!.$id,
|
276
|
+
indexes ?? []
|
277
|
+
);
|
278
|
+
}
|
279
|
+
// Process any remaining tasks in the queue
|
280
|
+
await processQueue(database, databaseId);
|
281
|
+
};
|
282
|
+
|
283
|
+
export const generateMockData = async (
|
284
|
+
database: Databases,
|
285
|
+
databaseId: string,
|
286
|
+
configCollections: any[]
|
287
|
+
): Promise<void> => {
|
288
|
+
for (const { collection, mockFunction } of configCollections) {
|
289
|
+
if (mockFunction) {
|
290
|
+
console.log(`Generating mock data for collection: ${collection.name}`);
|
291
|
+
const mockData = mockFunction();
|
292
|
+
for (const data of mockData) {
|
293
|
+
await database.createDocument(
|
294
|
+
databaseId,
|
295
|
+
collection.$id,
|
296
|
+
ID.unique(),
|
297
|
+
data
|
298
|
+
);
|
299
|
+
}
|
300
|
+
}
|
301
|
+
}
|
302
|
+
};
|
303
|
+
|
304
|
+
export const fetchAllCollections = async (
|
305
|
+
dbId: string,
|
306
|
+
database: Databases
|
307
|
+
): Promise<Models.Collection[]> => {
|
308
|
+
console.log(`Fetching all collections for database ID: ${dbId}`);
|
309
|
+
let collections: Models.Collection[] = [];
|
310
|
+
let moreCollections = true;
|
311
|
+
let lastCollectionId: string | undefined;
|
312
|
+
|
313
|
+
while (moreCollections) {
|
314
|
+
const queries = [Query.limit(500)];
|
315
|
+
if (lastCollectionId) {
|
316
|
+
queries.push(Query.cursorAfter(lastCollectionId));
|
317
|
+
}
|
318
|
+
const response = await tryAwaitWithRetry(
|
319
|
+
async () => await database.listCollections(dbId, queries)
|
320
|
+
);
|
321
|
+
collections = collections.concat(response.collections);
|
322
|
+
moreCollections = response.collections.length === 500;
|
323
|
+
if (moreCollections) {
|
324
|
+
lastCollectionId =
|
325
|
+
response.collections[response.collections.length - 1].$id;
|
326
|
+
}
|
327
|
+
}
|
328
|
+
|
329
|
+
console.log(`Fetched a total of ${collections.length} collections.`);
|
330
|
+
return collections;
|
331
|
+
};
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import { Databases, Query, type Models } from "node-appwrite";
|
2
|
+
import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
|
3
|
+
import { fetchAllCollections } from "../collections/methods.js";
|
4
|
+
|
5
|
+
export const fetchAllDatabases = async (
|
6
|
+
database: Databases
|
7
|
+
): Promise<Models.Database[]> => {
|
8
|
+
const databases = await tryAwaitWithRetry(
|
9
|
+
async () => await database.list([Query.limit(25)])
|
10
|
+
);
|
11
|
+
const allDatabases = databases.databases;
|
12
|
+
if (allDatabases.length === 0) return [];
|
13
|
+
let lastDatabaseId = allDatabases[allDatabases.length - 1].$id;
|
14
|
+
|
15
|
+
while (databases.databases.length === 25) {
|
16
|
+
const moreDatabases = await database.list([
|
17
|
+
Query.limit(25),
|
18
|
+
Query.cursorAfter(lastDatabaseId),
|
19
|
+
]);
|
20
|
+
allDatabases.push(...moreDatabases.databases);
|
21
|
+
if (moreDatabases.databases.length < 25) break;
|
22
|
+
lastDatabaseId =
|
23
|
+
moreDatabases.databases[moreDatabases.databases.length - 1].$id;
|
24
|
+
}
|
25
|
+
|
26
|
+
return allDatabases;
|
27
|
+
};
|
28
|
+
|
29
|
+
export const wipeDatabase = async (
|
30
|
+
database: Databases,
|
31
|
+
databaseId: string
|
32
|
+
): Promise<{ collectionId: string; collectionName: string }[]> => {
|
33
|
+
console.log(`Wiping database: ${databaseId}`);
|
34
|
+
const existingCollections = await fetchAllCollections(databaseId, database);
|
35
|
+
let collectionsDeleted: { collectionId: string; collectionName: string }[] =
|
36
|
+
[];
|
37
|
+
|
38
|
+
for (const { $id: collectionId, name } of existingCollections) {
|
39
|
+
console.log(`Deleting collection: ${collectionId}`);
|
40
|
+
collectionsDeleted.push({ collectionId, collectionName: name });
|
41
|
+
await tryAwaitWithRetry(
|
42
|
+
async () => await database.deleteCollection(databaseId, collectionId)
|
43
|
+
);
|
44
|
+
}
|
45
|
+
|
46
|
+
return collectionsDeleted;
|
47
|
+
};
|
package/src/init.ts
CHANGED
@@ -1,64 +1,64 @@
|
|
1
|
-
#!/usr/bin/env node
|
2
|
-
import inquirer from "inquirer";
|
3
|
-
import { createEmptyCollection, setupDirsFiles } from "./utils/setupFiles.js";
|
4
|
-
|
5
|
-
console.log("Welcome to Appwrite Utils CLI Tool by Zach Handley");
|
6
|
-
console.log(
|
7
|
-
"For more information, visit https://github.com/zachhandley/appwrite-utils"
|
8
|
-
);
|
9
|
-
|
10
|
-
async function main() {
|
11
|
-
const answers = await inquirer.prompt([
|
12
|
-
{
|
13
|
-
type: "list",
|
14
|
-
name: "action",
|
15
|
-
message: "What would you like to do?",
|
16
|
-
choices: [
|
17
|
-
"Create collection config file",
|
18
|
-
"Create function (not available)",
|
19
|
-
"Setup directories and files",
|
20
|
-
"Setup directories and files with example data",
|
21
|
-
"Exit",
|
22
|
-
],
|
23
|
-
},
|
24
|
-
]);
|
25
|
-
|
26
|
-
switch (answers.action) {
|
27
|
-
case "Create collection config file":
|
28
|
-
const { collectionName } = await inquirer.prompt([
|
29
|
-
{
|
30
|
-
type: "input",
|
31
|
-
name: "collectionName",
|
32
|
-
message: "Enter the name of the collection:",
|
33
|
-
validate: (input) =>
|
34
|
-
input.trim() !== "" || "Collection name cannot be empty.",
|
35
|
-
},
|
36
|
-
]);
|
37
|
-
console.log(`Creating collection config file for '${collectionName}'...`);
|
38
|
-
createEmptyCollection(collectionName);
|
39
|
-
break;
|
40
|
-
case "Create function (not available)":
|
41
|
-
console.log("This feature is not available yet.");
|
42
|
-
break;
|
43
|
-
case "Setup directories and files":
|
44
|
-
console.log("Setting up directories and files...");
|
45
|
-
setupDirsFiles(false); // Assuming false means no example data
|
46
|
-
break;
|
47
|
-
case "Setup directories and files with example data":
|
48
|
-
console.log("Setting up directories and files with example data...");
|
49
|
-
setupDirsFiles(true); // Assuming false means no example data
|
50
|
-
break;
|
51
|
-
case "Exit":
|
52
|
-
console.log("Exiting...");
|
53
|
-
process.exit(0);
|
54
|
-
break;
|
55
|
-
default:
|
56
|
-
console.log("Invalid option, please try again.");
|
57
|
-
break;
|
58
|
-
}
|
59
|
-
}
|
60
|
-
|
61
|
-
main().catch((error) => {
|
62
|
-
console.error("An error occurred:", error);
|
63
|
-
process.exit(1);
|
64
|
-
});
|
1
|
+
#!/usr/bin/env node
|
2
|
+
import inquirer from "inquirer";
|
3
|
+
import { createEmptyCollection, setupDirsFiles } from "./utils/setupFiles.js";
|
4
|
+
|
5
|
+
console.log("Welcome to Appwrite Utils CLI Tool by Zach Handley");
|
6
|
+
console.log(
|
7
|
+
"For more information, visit https://github.com/zachhandley/appwrite-utils"
|
8
|
+
);
|
9
|
+
|
10
|
+
async function main() {
|
11
|
+
const answers = await inquirer.prompt([
|
12
|
+
{
|
13
|
+
type: "list",
|
14
|
+
name: "action",
|
15
|
+
message: "What would you like to do?",
|
16
|
+
choices: [
|
17
|
+
"Create collection config file",
|
18
|
+
"Create function (not available)",
|
19
|
+
"Setup directories and files",
|
20
|
+
"Setup directories and files with example data",
|
21
|
+
"Exit",
|
22
|
+
],
|
23
|
+
},
|
24
|
+
]);
|
25
|
+
|
26
|
+
switch (answers.action) {
|
27
|
+
case "Create collection config file":
|
28
|
+
const { collectionName } = await inquirer.prompt([
|
29
|
+
{
|
30
|
+
type: "input",
|
31
|
+
name: "collectionName",
|
32
|
+
message: "Enter the name of the collection:",
|
33
|
+
validate: (input) =>
|
34
|
+
input.trim() !== "" || "Collection name cannot be empty.",
|
35
|
+
},
|
36
|
+
]);
|
37
|
+
console.log(`Creating collection config file for '${collectionName}'...`);
|
38
|
+
createEmptyCollection(collectionName);
|
39
|
+
break;
|
40
|
+
case "Create function (not available)":
|
41
|
+
console.log("This feature is not available yet.");
|
42
|
+
break;
|
43
|
+
case "Setup directories and files":
|
44
|
+
console.log("Setting up directories and files...");
|
45
|
+
setupDirsFiles(false); // Assuming false means no example data
|
46
|
+
break;
|
47
|
+
case "Setup directories and files with example data":
|
48
|
+
console.log("Setting up directories and files with example data...");
|
49
|
+
setupDirsFiles(true); // Assuming false means no example data
|
50
|
+
break;
|
51
|
+
case "Exit":
|
52
|
+
console.log("Exiting...");
|
53
|
+
process.exit(0);
|
54
|
+
break;
|
55
|
+
default:
|
56
|
+
console.log("Invalid option, please try again.");
|
57
|
+
break;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
main().catch((error) => {
|
62
|
+
console.error("An error occurred:", error);
|
63
|
+
process.exit(1);
|
64
|
+
});
|