appwrite-cli 1.2.1 → 2.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/README.md +4 -4
- package/docs/examples/account/create.md +1 -1
- package/docs/examples/account/update-password.md +1 -1
- package/docs/examples/console/variables.md +1 -0
- package/docs/examples/databases/create-relationship-attribute.md +9 -0
- package/docs/examples/databases/get-document.md +2 -1
- package/docs/examples/databases/update-boolean-attribute.md +6 -0
- package/docs/examples/databases/update-datetime-attribute.md +6 -0
- package/docs/examples/databases/update-email-attribute.md +6 -0
- package/docs/examples/databases/update-enum-attribute.md +7 -0
- package/docs/examples/databases/update-float-attribute.md +8 -0
- package/docs/examples/databases/update-integer-attribute.md +8 -0
- package/docs/examples/databases/update-ip-attribute.md +6 -0
- package/docs/examples/databases/update-relationship-attribute.md +5 -0
- package/docs/examples/databases/update-string-attribute.md +6 -0
- package/docs/examples/databases/update-url-attribute.md +6 -0
- package/docs/examples/functions/create.md +1 -1
- package/docs/examples/functions/update.md +1 -1
- package/docs/examples/projects/update-auth-password-dictionary.md +3 -0
- package/docs/examples/projects/update-auth-password-history.md +3 -0
- package/docs/examples/teams/create-membership.md +3 -1
- package/docs/examples/teams/get-prefs.md +2 -0
- package/docs/examples/teams/{update.md → update-name.md} +1 -1
- package/docs/examples/teams/update-prefs.md +3 -0
- package/docs/examples/users/update-password.md +1 -1
- package/index.js +2 -0
- package/install.ps1 +2 -2
- package/install.sh +1 -1
- package/lib/client.js +7 -7
- package/lib/commands/account.js +40 -7
- package/lib/commands/console.js +44 -0
- package/lib/commands/databases.js +727 -103
- package/lib/commands/deploy.js +270 -146
- package/lib/commands/functions.js +35 -9
- package/lib/commands/generic.js +6 -3
- package/lib/commands/init.js +215 -179
- package/lib/commands/projects.js +139 -5
- package/lib/commands/storage.js +39 -11
- package/lib/commands/teams.js +102 -16
- package/lib/commands/users.js +51 -2
- package/lib/config.js +84 -6
- package/lib/parser.js +7 -2
- package/lib/questions.js +307 -280
- package/package.json +1 -1
- package/docs/examples/account/get-logs.md +0 -2
- package/docs/examples/account/get-sessions.md +0 -1
- package/docs/examples/functions/retry-build.md +0 -4
- package/docs/examples/locale/get-continents.md +0 -1
- package/docs/examples/locale/get-countries-e-u.md +0 -1
- package/docs/examples/locale/get-countries-phones.md +0 -1
- package/docs/examples/locale/get-countries.md +0 -1
- package/docs/examples/locale/get-currencies.md +0 -1
- package/docs/examples/locale/get-languages.md +0 -1
- package/docs/examples/teams/get-memberships.md +0 -4
- package/docs/examples/users/get-logs.md +0 -3
- package/docs/examples/users/get-memberships.md +0 -2
- package/docs/examples/users/get-sessions.md +0 -2
package/lib/commands/deploy.js
CHANGED
|
@@ -2,12 +2,13 @@ const inquirer = require("inquirer");
|
|
|
2
2
|
const JSONbig = require("json-bigint")({ storeAsString: false });
|
|
3
3
|
const { Command } = require("commander");
|
|
4
4
|
const { localConfig } = require("../config");
|
|
5
|
-
const { questionsDeployTeams, questionsDeployFunctions, questionsGetEntrypoint, questionsDeployCollections, questionsConfirmDeployCollections } = require("../questions");
|
|
5
|
+
const { questionsDeployBuckets, questionsDeployTeams, questionsDeployFunctions, questionsGetEntrypoint, questionsDeployCollections, questionsConfirmDeployCollections } = require("../questions");
|
|
6
6
|
const { actionRunner, success, log, error, commandDescriptions } = require("../parser");
|
|
7
7
|
const { functionsGet, functionsCreate, functionsUpdate, functionsCreateDeployment, functionsUpdateDeployment, functionsListVariables, functionsDeleteVariable, functionsCreateVariable } = require('./functions');
|
|
8
8
|
const {
|
|
9
9
|
databasesGet,
|
|
10
10
|
databasesCreate,
|
|
11
|
+
databasesUpdate,
|
|
11
12
|
databasesCreateBooleanAttribute,
|
|
12
13
|
databasesGetCollection,
|
|
13
14
|
databasesCreateCollection,
|
|
@@ -20,11 +21,16 @@ const {
|
|
|
20
21
|
databasesCreateUrlAttribute,
|
|
21
22
|
databasesCreateIpAttribute,
|
|
22
23
|
databasesCreateEnumAttribute,
|
|
24
|
+
databasesCreateRelationshipAttribute,
|
|
23
25
|
databasesDeleteAttribute,
|
|
24
26
|
databasesListAttributes,
|
|
25
27
|
databasesListIndexes,
|
|
26
|
-
databasesDeleteIndex
|
|
28
|
+
databasesDeleteIndex,
|
|
29
|
+
databasesUpdateCollection
|
|
27
30
|
} = require("./databases");
|
|
31
|
+
const {
|
|
32
|
+
storageGetBucket, storageUpdateBucket, storageCreateBucket
|
|
33
|
+
} = require("./storage");
|
|
28
34
|
const {
|
|
29
35
|
teamsGet,
|
|
30
36
|
teamsUpdate,
|
|
@@ -44,7 +50,7 @@ const awaitPools = {
|
|
|
44
50
|
const { attributes: remoteAttributes } = await databasesListAttributes({
|
|
45
51
|
databaseId,
|
|
46
52
|
collectionId,
|
|
47
|
-
queries: [
|
|
53
|
+
queries: ['limit(100)'],
|
|
48
54
|
parseOutput: false
|
|
49
55
|
});
|
|
50
56
|
|
|
@@ -64,7 +70,7 @@ const awaitPools = {
|
|
|
64
70
|
const { indexes: remoteIndexes } = await databasesListIndexes({
|
|
65
71
|
databaseId,
|
|
66
72
|
collectionId,
|
|
67
|
-
queries: [
|
|
73
|
+
queries: ['limit(100)'],
|
|
68
74
|
parseOutput: false
|
|
69
75
|
});
|
|
70
76
|
|
|
@@ -84,7 +90,7 @@ const awaitPools = {
|
|
|
84
90
|
const { attributes: remoteAttributes } = await databasesListAttributes({
|
|
85
91
|
databaseId,
|
|
86
92
|
collectionId,
|
|
87
|
-
queries: [
|
|
93
|
+
queries: ['limit(100)'],
|
|
88
94
|
parseOutput: false
|
|
89
95
|
});
|
|
90
96
|
|
|
@@ -116,7 +122,7 @@ const awaitPools = {
|
|
|
116
122
|
const { indexes: remoteIndexes } = await databasesListIndexes({
|
|
117
123
|
databaseId,
|
|
118
124
|
collectionId,
|
|
119
|
-
queries: [
|
|
125
|
+
queries: ['limit(100)'],
|
|
120
126
|
parseOutput: false
|
|
121
127
|
});
|
|
122
128
|
|
|
@@ -155,9 +161,9 @@ const deployFunction = async ({ functionId, all, yes } = {}) => {
|
|
|
155
161
|
|
|
156
162
|
const functionIds = [];
|
|
157
163
|
|
|
158
|
-
if(functionId) {
|
|
164
|
+
if (functionId) {
|
|
159
165
|
functionIds.push(functionId);
|
|
160
|
-
} else if(all) {
|
|
166
|
+
} else if (all) {
|
|
161
167
|
const functions = localConfig.getFunctions();
|
|
162
168
|
if (functions.length === 0) {
|
|
163
169
|
throw new Error("No functions found in the current directory.");
|
|
@@ -167,22 +173,22 @@ const deployFunction = async ({ functionId, all, yes } = {}) => {
|
|
|
167
173
|
}));
|
|
168
174
|
}
|
|
169
175
|
|
|
170
|
-
if(functionIds.length <= 0) {
|
|
176
|
+
if (functionIds.length <= 0) {
|
|
171
177
|
const answers = await inquirer.prompt(questionsDeployFunctions[0]);
|
|
172
178
|
functionIds.push(...answers.functions);
|
|
173
179
|
}
|
|
174
180
|
|
|
175
181
|
let functions = functionIds.map((id) => {
|
|
176
|
-
|
|
177
|
-
|
|
182
|
+
const functions = localConfig.getFunctions();
|
|
183
|
+
const func = functions.find((f) => f.$id === id);
|
|
178
184
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
185
|
+
if (!func) {
|
|
186
|
+
throw new Error("Function '" + id + "' not found.")
|
|
187
|
+
}
|
|
182
188
|
|
|
183
|
-
|
|
189
|
+
return func;
|
|
184
190
|
});
|
|
185
|
-
|
|
191
|
+
|
|
186
192
|
for (let func of functions) {
|
|
187
193
|
log(`Deploying function ${func.name} ( ${func['$id']} )`)
|
|
188
194
|
|
|
@@ -192,50 +198,10 @@ const deployFunction = async ({ functionId, all, yes } = {}) => {
|
|
|
192
198
|
parseOutput: false,
|
|
193
199
|
});
|
|
194
200
|
|
|
195
|
-
if(response.runtime !== func.runtime) {
|
|
201
|
+
if (response.runtime !== func.runtime) {
|
|
196
202
|
throw new Error(`Runtime missmatch! (local=${func.runtime},remote=${response.runtime}) Please delete remote function or update your appwrite.json`);
|
|
197
203
|
}
|
|
198
204
|
|
|
199
|
-
if(func.variables) {
|
|
200
|
-
// Delete existing variables
|
|
201
|
-
|
|
202
|
-
// TODO: Pagination?
|
|
203
|
-
const { variables: remoteVariables } = await functionsListVariables({
|
|
204
|
-
functionId: func['$id'],
|
|
205
|
-
queries: [ 'limit(100)' ],
|
|
206
|
-
parseOutput: false
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
if(remoteVariables.length > 0) {
|
|
210
|
-
if(!yes) {
|
|
211
|
-
const variableAnswers = await inquirer.prompt(questionsDeployFunctions[1])
|
|
212
|
-
|
|
213
|
-
if (variableAnswers.override !== "YES") {
|
|
214
|
-
log(`Received "${variableAnswers.override}". Skipping ${func.name} ( ${func['$id']} )`);
|
|
215
|
-
continue;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
await Promise.all(remoteVariables.map(async remoteVariable => {
|
|
220
|
-
await functionsDeleteVariable({
|
|
221
|
-
functionId: func['$id'],
|
|
222
|
-
variableId: remoteVariable['$id'],
|
|
223
|
-
parseOutput: false
|
|
224
|
-
});
|
|
225
|
-
}));
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Deploy local variables
|
|
229
|
-
await Promise.all(Object.keys(func.variables).map(async localVariableKey => {
|
|
230
|
-
await functionsCreateVariable({
|
|
231
|
-
functionId: func['$id'],
|
|
232
|
-
key: localVariableKey,
|
|
233
|
-
value: func.variables[localVariableKey],
|
|
234
|
-
parseOutput: false
|
|
235
|
-
});
|
|
236
|
-
}));
|
|
237
|
-
}
|
|
238
|
-
|
|
239
205
|
response = await functionsUpdate({
|
|
240
206
|
functionId: func['$id'],
|
|
241
207
|
name: func.name,
|
|
@@ -272,6 +238,49 @@ const deployFunction = async ({ functionId, all, yes } = {}) => {
|
|
|
272
238
|
}
|
|
273
239
|
}
|
|
274
240
|
|
|
241
|
+
if (func.variables) {
|
|
242
|
+
// Delete existing variables
|
|
243
|
+
|
|
244
|
+
// TODO: Pagination?
|
|
245
|
+
const { variables: remoteVariables } = await functionsListVariables({
|
|
246
|
+
functionId: func['$id'],
|
|
247
|
+
queries: ['limit(100)'],
|
|
248
|
+
parseOutput: false
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
let deployVariables = yes;
|
|
252
|
+
if (remoteVariables.length == 0) {
|
|
253
|
+
deployVariables = true;
|
|
254
|
+
} else if (remoteVariables.length > 0 && !yes) {
|
|
255
|
+
const variableAnswers = await inquirer.prompt(questionsDeployFunctions[1])
|
|
256
|
+
deployVariables = variableAnswers.override === "YES";
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (!deployVariables) {
|
|
260
|
+
log(`Skipping variables for ${func.name} ( ${func['$id']} )`);
|
|
261
|
+
} else {
|
|
262
|
+
log(`Deploying variables for ${func.name} ( ${func['$id']} )`);
|
|
263
|
+
|
|
264
|
+
await Promise.all(remoteVariables.map(async remoteVariable => {
|
|
265
|
+
await functionsDeleteVariable({
|
|
266
|
+
functionId: func['$id'],
|
|
267
|
+
variableId: remoteVariable['$id'],
|
|
268
|
+
parseOutput: false
|
|
269
|
+
});
|
|
270
|
+
}));
|
|
271
|
+
|
|
272
|
+
// Deploy local variables
|
|
273
|
+
await Promise.all(Object.keys(func.variables).map(async localVariableKey => {
|
|
274
|
+
await functionsCreateVariable({
|
|
275
|
+
functionId: func['$id'],
|
|
276
|
+
key: localVariableKey,
|
|
277
|
+
value: func.variables[localVariableKey],
|
|
278
|
+
parseOutput: false
|
|
279
|
+
});
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
275
284
|
// Create tag
|
|
276
285
|
if (!func.entrypoint) {
|
|
277
286
|
answers = await inquirer.prompt(questionsGetEntrypoint)
|
|
@@ -300,6 +309,8 @@ const deployFunction = async ({ functionId, all, yes } = {}) => {
|
|
|
300
309
|
}
|
|
301
310
|
}
|
|
302
311
|
}
|
|
312
|
+
|
|
313
|
+
success(`Deployed ${functions.length} functions`);
|
|
303
314
|
}
|
|
304
315
|
|
|
305
316
|
const createAttribute = async (databaseId, collectionId, attribute) => {
|
|
@@ -404,50 +415,69 @@ const createAttribute = async (databaseId, collectionId, attribute) => {
|
|
|
404
415
|
array: attribute.array,
|
|
405
416
|
parseOutput: false
|
|
406
417
|
})
|
|
418
|
+
case 'relationship':
|
|
419
|
+
return databasesCreateRelationshipAttribute({
|
|
420
|
+
databaseId,
|
|
421
|
+
collectionId,
|
|
422
|
+
relatedCollectionId: attribute.relatedCollection,
|
|
423
|
+
type: attribute.relationType,
|
|
424
|
+
twoWay: attribute.twoWay,
|
|
425
|
+
key: attribute.key,
|
|
426
|
+
twoWayKey: attribute.twoWayKey,
|
|
427
|
+
onDelete: attribute.onDelete,
|
|
428
|
+
parseOutput: false
|
|
429
|
+
})
|
|
407
430
|
}
|
|
408
431
|
}
|
|
409
432
|
|
|
410
433
|
const deployCollection = async ({ all, yes } = {}) => {
|
|
411
434
|
let response = {};
|
|
412
435
|
|
|
413
|
-
|
|
414
|
-
const configCollections = localConfig.getCollections();
|
|
436
|
+
const collections = [];
|
|
415
437
|
|
|
416
|
-
if(all) {
|
|
417
|
-
if (
|
|
438
|
+
if (all) {
|
|
439
|
+
if (localConfig.getCollections().length === 0) {
|
|
418
440
|
throw new Error("No collections found in the current directory. Run `appwrite init collection` to fetch all your collections.");
|
|
419
441
|
}
|
|
420
|
-
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
const idCollections = configCollections.filter((c) => c.$id === collectionId);
|
|
432
|
-
collections.push(...idCollections);
|
|
442
|
+
collections.push(...localConfig.getCollections());
|
|
443
|
+
} else {
|
|
444
|
+
const answers = await inquirer.prompt(questionsDeployCollections[0])
|
|
445
|
+
const configCollections = new Map();
|
|
446
|
+
localConfig.getCollections().forEach((c) => {
|
|
447
|
+
configCollections.set(`${c['databaseId']}|${c['$id']}`, c);
|
|
448
|
+
});
|
|
449
|
+
answers.collections.forEach((a) => {
|
|
450
|
+
const collection = configCollections.get(a);
|
|
451
|
+
collections.push(collection);
|
|
452
|
+
})
|
|
433
453
|
}
|
|
434
454
|
|
|
435
455
|
for (let collection of collections) {
|
|
436
|
-
log(`Deploying collection ${collection.name} ( ${collection['$id']} )`)
|
|
456
|
+
log(`Deploying collection ${collection.name} ( ${collection['databaseId']} - ${collection['$id']} )`)
|
|
437
457
|
|
|
438
458
|
let databaseId;
|
|
439
459
|
|
|
460
|
+
const localDatabase = localConfig.getDatabase(collection.databaseId);
|
|
461
|
+
|
|
440
462
|
try {
|
|
441
463
|
const database = await databasesGet({
|
|
442
464
|
databaseId: collection.databaseId,
|
|
443
465
|
parseOutput: false,
|
|
444
466
|
});
|
|
445
467
|
databaseId = database.$id;
|
|
446
|
-
|
|
468
|
+
|
|
469
|
+
await databasesUpdate({
|
|
470
|
+
databaseId: collection.databaseId,
|
|
471
|
+
name: localDatabase.name ?? collection.databaseId,
|
|
472
|
+
parseOutput: false
|
|
473
|
+
})
|
|
474
|
+
|
|
475
|
+
success(`Updated ${localDatabase.name} ( ${collection.databaseId} )`);
|
|
476
|
+
} catch (err) {
|
|
447
477
|
log(`Database ${collection.databaseId} not found. Creating it now...`);
|
|
448
478
|
const database = await databasesCreate({
|
|
449
479
|
databaseId: collection.databaseId,
|
|
450
|
-
name: collection.databaseId,
|
|
480
|
+
name: localDatabase.name ?? collection.databaseId,
|
|
451
481
|
parseOutput: false,
|
|
452
482
|
});
|
|
453
483
|
databaseId = database.$id;
|
|
@@ -461,7 +491,7 @@ const deployCollection = async ({ all, yes } = {}) => {
|
|
|
461
491
|
})
|
|
462
492
|
log(`Collection ${collection.name} ( ${collection['$id']} ) already exists.`);
|
|
463
493
|
|
|
464
|
-
if(!yes) {
|
|
494
|
+
if (!yes) {
|
|
465
495
|
answers = await inquirer.prompt(questionsDeployCollections[1])
|
|
466
496
|
if (answers.override !== "YES") {
|
|
467
497
|
log(`Received "${answers.override}". Skipping ${collection.name} ( ${collection['$id']} )`);
|
|
@@ -469,13 +499,13 @@ const deployCollection = async ({ all, yes } = {}) => {
|
|
|
469
499
|
}
|
|
470
500
|
}
|
|
471
501
|
|
|
472
|
-
log(`
|
|
502
|
+
log(`Deleting indexes and attributes ... `);
|
|
473
503
|
|
|
474
504
|
// TODO: Pagination?
|
|
475
505
|
const { indexes: remoteIndexes } = await databasesListIndexes({
|
|
476
506
|
databaseId,
|
|
477
507
|
collectionId: collection['$id'],
|
|
478
|
-
queries: [
|
|
508
|
+
queries: ['limit(100)'],
|
|
479
509
|
parseOutput: false
|
|
480
510
|
});
|
|
481
511
|
|
|
@@ -497,10 +527,10 @@ const deployCollection = async ({ all, yes } = {}) => {
|
|
|
497
527
|
const { attributes: remoteAttributes } = await databasesListAttributes({
|
|
498
528
|
databaseId,
|
|
499
529
|
collectionId: collection['$id'],
|
|
500
|
-
queries: [
|
|
530
|
+
queries: ['limit(100)'],
|
|
501
531
|
parseOutput: false
|
|
502
532
|
});
|
|
503
|
-
|
|
533
|
+
|
|
504
534
|
await Promise.all(remoteAttributes.map(async attribute => {
|
|
505
535
|
await databasesDeleteAttribute({
|
|
506
536
|
databaseId,
|
|
@@ -515,38 +545,15 @@ const deployCollection = async ({ all, yes } = {}) => {
|
|
|
515
545
|
throw new Error("Attribute deletion did not finish for too long.");
|
|
516
546
|
}
|
|
517
547
|
|
|
518
|
-
await
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
success(`Created ${collection.attributes.length} attributes`);
|
|
529
|
-
|
|
530
|
-
log(`Creating indexes ...`)
|
|
531
|
-
await Promise.all(collection.indexes.map(async index => {
|
|
532
|
-
await databasesCreateIndex({
|
|
533
|
-
databaseId,
|
|
534
|
-
collectionId: collection['$id'],
|
|
535
|
-
key: index.key,
|
|
536
|
-
type: index.type,
|
|
537
|
-
attributes: index.attributes,
|
|
538
|
-
orders: index.orders,
|
|
539
|
-
parseOutput: false
|
|
540
|
-
});
|
|
541
|
-
}));
|
|
542
|
-
|
|
543
|
-
const indexKeys = collection.indexes.map(attribute => attribute.key);
|
|
544
|
-
const indexPoolStatus = await awaitPools.expectIndexes(databaseId, collection['$id'], indexKeys);
|
|
545
|
-
if (!indexPoolStatus) {
|
|
546
|
-
throw new Error("Index creation did not finish for too long.");
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
success(`Created ${collection.indexes.length} indexes`);
|
|
548
|
+
await databasesUpdateCollection({
|
|
549
|
+
databaseId,
|
|
550
|
+
collectionId: collection['$id'],
|
|
551
|
+
name: collection.name,
|
|
552
|
+
documentSecurity: collection.documentSecurity,
|
|
553
|
+
permissions: collection['$permissions'],
|
|
554
|
+
enabled: collection.enabled,
|
|
555
|
+
parseOutput: false
|
|
556
|
+
})
|
|
550
557
|
} catch (e) {
|
|
551
558
|
if (e.code == 404) {
|
|
552
559
|
log(`Collection ${collection.name} does not exist in the project. Creating ... `);
|
|
@@ -559,41 +566,151 @@ const deployCollection = async ({ all, yes } = {}) => {
|
|
|
559
566
|
parseOutput: false
|
|
560
567
|
})
|
|
561
568
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
569
|
+
} else {
|
|
570
|
+
throw e;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
566
573
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
574
|
+
// Create all non-relationship attributes first
|
|
575
|
+
const nonRelationshipAttributes = collection.attributes.filter(attribute => attribute.type !== 'relationship');
|
|
576
|
+
await Promise.all(nonRelationshipAttributes.map(attribute => {
|
|
577
|
+
return createAttribute(databaseId, collection['$id'], attribute);
|
|
578
|
+
}));
|
|
572
579
|
|
|
573
|
-
|
|
580
|
+
const nonRelationshipAttributeKeys = nonRelationshipAttributes.map(attribute => attribute.key);
|
|
581
|
+
const createPoolStatus = await awaitPools.expectAttributes(databaseId, collection['$id'], nonRelationshipAttributeKeys);
|
|
582
|
+
if (!createPoolStatus) {
|
|
583
|
+
throw new Error("Attribute creation did not finish for too long.");
|
|
584
|
+
}
|
|
574
585
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
586
|
+
success(`Created ${nonRelationshipAttributeKeys.length} non-relationship attributes`);
|
|
587
|
+
|
|
588
|
+
log(`Creating indexes ...`)
|
|
589
|
+
await Promise.all(collection.indexes.map(async index => {
|
|
590
|
+
await databasesCreateIndex({
|
|
591
|
+
databaseId,
|
|
592
|
+
collectionId: collection['$id'],
|
|
593
|
+
key: index.key,
|
|
594
|
+
type: index.type,
|
|
595
|
+
attributes: index.attributes,
|
|
596
|
+
orders: index.orders,
|
|
597
|
+
parseOutput: false
|
|
598
|
+
});
|
|
599
|
+
}));
|
|
600
|
+
|
|
601
|
+
const indexKeys = collection.indexes.map(attribute => attribute.key);
|
|
602
|
+
const indexPoolStatus = await awaitPools.expectIndexes(databaseId, collection['$id'], indexKeys);
|
|
603
|
+
if (!indexPoolStatus) {
|
|
604
|
+
throw new Error("Index creation did not finish for too long.");
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
success(`Created ${collection.indexes.length} indexes`);
|
|
608
|
+
|
|
609
|
+
success(`Deployed ${collection.name} ( ${collection['$id']} )`);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Create the relationship attributes
|
|
613
|
+
for (let collection of collections) {
|
|
614
|
+
const relationshipAttributes = collection.attributes.filter(attribute => attribute.type === 'relationship' && attribute.side === 'parent');
|
|
615
|
+
|
|
616
|
+
if (relationshipAttributes.length === 0) continue;
|
|
587
617
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
618
|
+
log(`Deploying relationships for collection ${collection.name} ( ${collection['$id']} )`);
|
|
619
|
+
|
|
620
|
+
await Promise.all(relationshipAttributes.map(attribute => {
|
|
621
|
+
return createAttribute(collection['databaseId'], collection['$id'], attribute);
|
|
622
|
+
}));
|
|
623
|
+
|
|
624
|
+
const nonRelationshipAttributeKeys = relationshipAttributes.map(attribute => attribute.key);
|
|
625
|
+
const createPoolStatus = await awaitPools.expectAttributes(collection['databaseId'], collection['$id'], nonRelationshipAttributeKeys);
|
|
626
|
+
if (!createPoolStatus) {
|
|
627
|
+
throw new Error("Attribute creation did not finish for too long.");
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
success(`Created ${nonRelationshipAttributeKeys.length} relationship attributes`);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
const deployBucket = async ({ all, yes } = {}) => {
|
|
635
|
+
let response = {};
|
|
636
|
+
|
|
637
|
+
let bucketIds = [];
|
|
638
|
+
const configBuckets = localConfig.getBuckets();
|
|
639
|
+
|
|
640
|
+
if (all) {
|
|
641
|
+
if (configBuckets.length === 0) {
|
|
642
|
+
throw new Error("No buckets found in the current directory. Run `appwrite init bucket` to fetch all your buckets.");
|
|
643
|
+
}
|
|
644
|
+
bucketIds.push(...configBuckets.map((b) => b.$id));
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
if (bucketIds.length === 0) {
|
|
648
|
+
let answers = await inquirer.prompt(questionsDeployBuckets[0])
|
|
649
|
+
bucketIds.push(...answers.buckets);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
let buckets = [];
|
|
653
|
+
|
|
654
|
+
for (const bucketId of bucketIds) {
|
|
655
|
+
const idBuckets = configBuckets.filter((b) => b.$id === bucketId);
|
|
656
|
+
buckets.push(...idBuckets);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
for (let bucket of buckets) {
|
|
660
|
+
log(`Deploying bucket ${bucket.name} ( ${bucket['$id']} )`)
|
|
661
|
+
|
|
662
|
+
try {
|
|
663
|
+
response = await storageGetBucket({
|
|
664
|
+
bucketId: bucket['$id'],
|
|
665
|
+
parseOutput: false,
|
|
666
|
+
})
|
|
667
|
+
log(`Bucket ${bucket.name} ( ${bucket['$id']} ) already exists.`);
|
|
668
|
+
|
|
669
|
+
if (!yes) {
|
|
670
|
+
answers = await inquirer.prompt(questionsDeployBuckets[1])
|
|
671
|
+
if (answers.override !== "YES") {
|
|
672
|
+
log(`Received "${answers.override}". Skipping ${bucket.name} ( ${bucket['$id']} )`);
|
|
673
|
+
continue;
|
|
592
674
|
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
log(`Updating bucket ...`)
|
|
678
|
+
|
|
679
|
+
await storageUpdateBucket({
|
|
680
|
+
bucketId: bucket['$id'],
|
|
681
|
+
name: bucket.name,
|
|
682
|
+
permissions: bucket['$permissions'],
|
|
683
|
+
fileSecurity: bucket.fileSecurity,
|
|
684
|
+
enabled: bucket.enabled,
|
|
685
|
+
maximumFileSize: bucket.maximumFileSize,
|
|
686
|
+
allowedFileExtensions: bucket.allowedFileExtensions,
|
|
687
|
+
compression: bucket.compression,
|
|
688
|
+
encryption: bucket.encryption,
|
|
689
|
+
antivirus: bucket.antivirus,
|
|
690
|
+
compression: bucket.compression,
|
|
691
|
+
parseOutput: false
|
|
692
|
+
});
|
|
593
693
|
|
|
594
|
-
|
|
694
|
+
success(`Deployed ${bucket.name} ( ${bucket['$id']} )`);
|
|
695
|
+
} catch (e) {
|
|
696
|
+
if (e.code == 404) {
|
|
697
|
+
log(`Bucket ${bucket.name} does not exist in the project. Creating ... `);
|
|
698
|
+
|
|
699
|
+
response = await storageCreateBucket({
|
|
700
|
+
bucketId: bucket['$id'],
|
|
701
|
+
name: bucket.name,
|
|
702
|
+
permissions: bucket['$permissions'],
|
|
703
|
+
fileSecurity: bucket.fileSecurity,
|
|
704
|
+
enabled: bucket.enabled,
|
|
705
|
+
maximumFileSize: bucket.maximumFileSize,
|
|
706
|
+
allowedFileExtensions: bucket.allowedFileExtensions,
|
|
707
|
+
compression: bucket.compression,
|
|
708
|
+
encryption: bucket.encryption,
|
|
709
|
+
antivirus: bucket.antivirus,
|
|
710
|
+
parseOutput: false
|
|
711
|
+
})
|
|
595
712
|
|
|
596
|
-
success(`Deployed ${
|
|
713
|
+
success(`Deployed ${bucket.name} ( ${bucket['$id']} )`);
|
|
597
714
|
} else {
|
|
598
715
|
throw e;
|
|
599
716
|
}
|
|
@@ -607,21 +724,21 @@ const deployTeam = async ({ all, yes } = {}) => {
|
|
|
607
724
|
let teamIds = [];
|
|
608
725
|
const configTeams = localConfig.getTeams();
|
|
609
726
|
|
|
610
|
-
if(all) {
|
|
727
|
+
if (all) {
|
|
611
728
|
if (configTeams.length === 0) {
|
|
612
729
|
throw new Error("No teams found in the current directory. Run `appwrite init team` to fetch all your teams.");
|
|
613
730
|
}
|
|
614
731
|
teamIds.push(...configTeams.map((t) => t.$id));
|
|
615
732
|
}
|
|
616
733
|
|
|
617
|
-
if(teamIds.length === 0) {
|
|
734
|
+
if (teamIds.length === 0) {
|
|
618
735
|
let answers = await inquirer.prompt(questionsDeployTeams[0])
|
|
619
736
|
teamIds.push(...answers.teams);
|
|
620
737
|
}
|
|
621
738
|
|
|
622
739
|
let teams = [];
|
|
623
740
|
|
|
624
|
-
for(const teamId of teamIds) {
|
|
741
|
+
for (const teamId of teamIds) {
|
|
625
742
|
const idTeams = configTeams.filter((t) => t.$id === teamId);
|
|
626
743
|
teams.push(...idTeams);
|
|
627
744
|
}
|
|
@@ -636,7 +753,7 @@ const deployTeam = async ({ all, yes } = {}) => {
|
|
|
636
753
|
})
|
|
637
754
|
log(`Team ${team.name} ( ${team['$id']} ) already exists.`);
|
|
638
755
|
|
|
639
|
-
if(!yes) {
|
|
756
|
+
if (!yes) {
|
|
640
757
|
answers = await inquirer.prompt(questionsDeployTeams[1])
|
|
641
758
|
if (answers.override !== "YES") {
|
|
642
759
|
log(`Received "${answers.override}". Skipping ${team.name} ( ${team['$id']} )`);
|
|
@@ -686,6 +803,13 @@ deploy
|
|
|
686
803
|
.option(`--yes`, `Flag to confirm all warnings`)
|
|
687
804
|
.action(actionRunner(deployCollection));
|
|
688
805
|
|
|
806
|
+
deploy
|
|
807
|
+
.command("bucket")
|
|
808
|
+
.description("Deploy buckets in the current project.")
|
|
809
|
+
.option(`--all`, `Flag to deploy all buckets`)
|
|
810
|
+
.option(`--yes`, `Flag to confirm all warnings`)
|
|
811
|
+
.action(actionRunner(deployBucket));
|
|
812
|
+
|
|
689
813
|
deploy
|
|
690
814
|
.command("team")
|
|
691
815
|
.description("Deploy teams in the current project.")
|