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.
Files changed (57) hide show
  1. package/README.md +4 -4
  2. package/docs/examples/account/create.md +1 -1
  3. package/docs/examples/account/update-password.md +1 -1
  4. package/docs/examples/console/variables.md +1 -0
  5. package/docs/examples/databases/create-relationship-attribute.md +9 -0
  6. package/docs/examples/databases/get-document.md +2 -1
  7. package/docs/examples/databases/update-boolean-attribute.md +6 -0
  8. package/docs/examples/databases/update-datetime-attribute.md +6 -0
  9. package/docs/examples/databases/update-email-attribute.md +6 -0
  10. package/docs/examples/databases/update-enum-attribute.md +7 -0
  11. package/docs/examples/databases/update-float-attribute.md +8 -0
  12. package/docs/examples/databases/update-integer-attribute.md +8 -0
  13. package/docs/examples/databases/update-ip-attribute.md +6 -0
  14. package/docs/examples/databases/update-relationship-attribute.md +5 -0
  15. package/docs/examples/databases/update-string-attribute.md +6 -0
  16. package/docs/examples/databases/update-url-attribute.md +6 -0
  17. package/docs/examples/functions/create.md +1 -1
  18. package/docs/examples/functions/update.md +1 -1
  19. package/docs/examples/projects/update-auth-password-dictionary.md +3 -0
  20. package/docs/examples/projects/update-auth-password-history.md +3 -0
  21. package/docs/examples/teams/create-membership.md +3 -1
  22. package/docs/examples/teams/get-prefs.md +2 -0
  23. package/docs/examples/teams/{update.md → update-name.md} +1 -1
  24. package/docs/examples/teams/update-prefs.md +3 -0
  25. package/docs/examples/users/update-password.md +1 -1
  26. package/index.js +2 -0
  27. package/install.ps1 +2 -2
  28. package/install.sh +1 -1
  29. package/lib/client.js +7 -7
  30. package/lib/commands/account.js +40 -7
  31. package/lib/commands/console.js +44 -0
  32. package/lib/commands/databases.js +727 -103
  33. package/lib/commands/deploy.js +270 -146
  34. package/lib/commands/functions.js +35 -9
  35. package/lib/commands/generic.js +6 -3
  36. package/lib/commands/init.js +215 -179
  37. package/lib/commands/projects.js +139 -5
  38. package/lib/commands/storage.js +39 -11
  39. package/lib/commands/teams.js +102 -16
  40. package/lib/commands/users.js +51 -2
  41. package/lib/config.js +84 -6
  42. package/lib/parser.js +7 -2
  43. package/lib/questions.js +307 -280
  44. package/package.json +1 -1
  45. package/docs/examples/account/get-logs.md +0 -2
  46. package/docs/examples/account/get-sessions.md +0 -1
  47. package/docs/examples/functions/retry-build.md +0 -4
  48. package/docs/examples/locale/get-continents.md +0 -1
  49. package/docs/examples/locale/get-countries-e-u.md +0 -1
  50. package/docs/examples/locale/get-countries-phones.md +0 -1
  51. package/docs/examples/locale/get-countries.md +0 -1
  52. package/docs/examples/locale/get-currencies.md +0 -1
  53. package/docs/examples/locale/get-languages.md +0 -1
  54. package/docs/examples/teams/get-memberships.md +0 -4
  55. package/docs/examples/users/get-logs.md +0 -3
  56. package/docs/examples/users/get-memberships.md +0 -2
  57. package/docs/examples/users/get-sessions.md +0 -2
@@ -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: [ 'limit(100)' ],
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: [ 'limit(100)' ],
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: [ 'limit(100)' ],
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: [ 'limit(100)' ],
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
- const functions = localConfig.getFunctions();
177
- const func = functions.find((f) => f.$id === id);
182
+ const functions = localConfig.getFunctions();
183
+ const func = functions.find((f) => f.$id === id);
178
184
 
179
- if(!func) {
180
- throw new Error("Function '" + id + "' not found.")
181
- }
185
+ if (!func) {
186
+ throw new Error("Function '" + id + "' not found.")
187
+ }
182
188
 
183
- return func;
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
- let collectionIds = [];
414
- const configCollections = localConfig.getCollections();
436
+ const collections = [];
415
437
 
416
- if(all) {
417
- if (configCollections.length === 0) {
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
- collectionIds.push(...configCollections.map((c) => c.$id));
421
- }
422
-
423
- if(collectionIds.length <= 0) {
424
- let answers = await inquirer.prompt(questionsDeployCollections[0])
425
- collectionIds.push(...answers.collections);
426
- }
427
-
428
- let collections = [];
429
-
430
- for(const collectionId of collectionIds) {
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
- } catch(err) {
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(`Updating attributes ... `);
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: [ 'limit(100)' ],
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: [ 'limit(100)' ],
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 Promise.all(collection.attributes.map(async attribute => {
519
- await createAttribute(databaseId, collection['$id'], attribute);
520
- }));
521
-
522
- const attributeKeys = collection.attributes.map(attribute => attribute.key);
523
- const createPoolStatus = await awaitPools.expectAttributes(databaseId, collection['$id'], attributeKeys);
524
- if (!createPoolStatus) {
525
- throw new Error("Attribute creation did not finish for too long.");
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
- log(`Creating attributes ... `);
563
- await Promise.all(collection.attributes.map(async attribute => {
564
- await createAttribute(databaseId, collection['$id'], attribute);
565
- }));
569
+ } else {
570
+ throw e;
571
+ }
572
+ }
566
573
 
567
- const attributeKeys = collection.attributes.map(attribute => attribute.key);
568
- const attributePoolStatus = await awaitPools.expectAttributes(databaseId, collection['$id'], attributeKeys);
569
- if (!attributePoolStatus) {
570
- throw new Error("Attribute creation did not finish for too long.");
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
- success(`Created ${collection.attributes.length} attributes`);
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
- log(`Creating indexes ...`);
576
- await Promise.all(collection.indexes.map(async index => {
577
- await databasesCreateIndex({
578
- databaseId,
579
- collectionId: collection['$id'],
580
- key: index.key,
581
- type: index.type,
582
- attributes: index.attributes,
583
- orders: index.orders,
584
- parseOutput: false
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
- const indexKeys = collection.indexes.map(attribute => attribute.key);
589
- const indexPoolStatus = await awaitPools.expectIndexes(databaseId, collection['$id'], indexKeys);
590
- if (!indexPoolStatus) {
591
- throw new Error("Index creation did not finish for too long.");
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
- success(`Created ${collection.indexes.length} indexes`);
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 ${collection.name} ( ${collection['$id']} )`);
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.")