appwrite-cli 5.0.5 → 6.0.0-rc.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 (53) hide show
  1. package/README.md +4 -4
  2. package/docs/examples/functions/create-build.md +1 -1
  3. package/docs/examples/functions/create-execution.md +1 -0
  4. package/docs/examples/functions/create.md +1 -0
  5. package/docs/examples/functions/delete-execution.md +3 -0
  6. package/docs/examples/functions/update-deployment-build.md +3 -0
  7. package/docs/examples/functions/update.md +1 -0
  8. package/docs/examples/projects/create-j-w-t.md +4 -0
  9. package/docs/examples/projects/update-mock-numbers.md +3 -0
  10. package/docs/examples/projects/update-session-alerts.md +3 -0
  11. package/docs/examples/users/create-j-w-t.md +4 -0
  12. package/docs/examples/vcs/get-repository-contents.md +4 -0
  13. package/index.js +34 -7
  14. package/install.ps1 +3 -3
  15. package/install.sh +2 -2
  16. package/lib/client.js +17 -3
  17. package/lib/commands/account.js +306 -152
  18. package/lib/commands/assistant.js +8 -5
  19. package/lib/commands/avatars.js +114 -58
  20. package/lib/commands/console.js +8 -5
  21. package/lib/commands/databases.js +353 -164
  22. package/lib/commands/functions.js +310 -100
  23. package/lib/commands/generic.js +206 -54
  24. package/lib/commands/graphql.js +14 -8
  25. package/lib/commands/health.js +140 -71
  26. package/lib/commands/init.js +250 -155
  27. package/lib/commands/locale.js +50 -26
  28. package/lib/commands/messaging.js +334 -156
  29. package/lib/commands/migrations.js +98 -50
  30. package/lib/commands/project.js +38 -20
  31. package/lib/commands/projects.js +449 -144
  32. package/lib/commands/proxy.js +32 -17
  33. package/lib/commands/pull.js +231 -0
  34. package/lib/commands/push.js +1518 -0
  35. package/lib/commands/run.js +282 -0
  36. package/lib/commands/storage.js +160 -76
  37. package/lib/commands/teams.js +102 -50
  38. package/lib/commands/users.js +324 -134
  39. package/lib/commands/vcs.js +102 -29
  40. package/lib/config.js +190 -18
  41. package/lib/emulation/docker.js +187 -0
  42. package/lib/emulation/utils.js +177 -0
  43. package/lib/id.js +30 -0
  44. package/lib/paginate.js +1 -2
  45. package/lib/parser.js +69 -12
  46. package/lib/questions.js +452 -80
  47. package/lib/sdks.js +1 -1
  48. package/lib/spinner.js +103 -0
  49. package/lib/utils.js +242 -4
  50. package/lib/validations.js +17 -0
  51. package/package.json +6 -2
  52. package/scoop/appwrite.json +3 -3
  53. package/lib/commands/deploy.js +0 -940
@@ -1,940 +0,0 @@
1
- const inquirer = require("inquirer");
2
- const JSONbig = require("json-bigint")({ storeAsString: false });
3
- const { Command } = require("commander");
4
- const { localConfig } = require("../config");
5
- const { paginate } = require('../paginate');
6
- const { questionsDeployBuckets, questionsDeployTeams, questionsDeployFunctions, questionsGetEntrypoint, questionsDeployCollections, questionsConfirmDeployCollections } = require("../questions");
7
- const { actionRunner, success, log, error, commandDescriptions } = require("../parser");
8
- const { functionsGet, functionsCreate, functionsUpdate, functionsCreateDeployment, functionsUpdateDeployment, functionsListVariables, functionsDeleteVariable, functionsCreateVariable } = require('./functions');
9
- const {
10
- databasesGet,
11
- databasesCreate,
12
- databasesUpdate,
13
- databasesCreateBooleanAttribute,
14
- databasesGetCollection,
15
- databasesCreateCollection,
16
- databasesCreateStringAttribute,
17
- databasesCreateIntegerAttribute,
18
- databasesCreateFloatAttribute,
19
- databasesCreateEmailAttribute,
20
- databasesCreateDatetimeAttribute,
21
- databasesCreateIndex,
22
- databasesCreateUrlAttribute,
23
- databasesCreateIpAttribute,
24
- databasesCreateEnumAttribute,
25
- databasesCreateRelationshipAttribute,
26
- databasesDeleteAttribute,
27
- databasesListAttributes,
28
- databasesListIndexes,
29
- databasesDeleteIndex,
30
- databasesUpdateCollection
31
- } = require("./databases");
32
- const {
33
- storageGetBucket, storageUpdateBucket, storageCreateBucket
34
- } = require("./storage");
35
- const {
36
- teamsGet,
37
- teamsUpdateName,
38
- teamsCreate
39
- } = require("./teams");
40
- const { checkDeployConditions } = require('../utils');
41
-
42
- const STEP_SIZE = 100; // Resources
43
- const POOL_DEBOUNCE = 2000; // Milliseconds
44
-
45
- let poolMaxDebounces = 30;
46
-
47
- const awaitPools = {
48
- wipeAttributes: async (databaseId, collectionId, iteration = 1) => {
49
- if (iteration > poolMaxDebounces) {
50
- return false;
51
- }
52
-
53
- const { total } = await databasesListAttributes({
54
- databaseId,
55
- collectionId,
56
- queries: [JSON.stringify({ method: 'limit', values: [1] })],
57
- parseOutput: false
58
- });
59
-
60
- if (total === 0) {
61
- return true;
62
- }
63
-
64
- let steps = Math.max(1, Math.ceil(total / STEP_SIZE));
65
- if (steps > 1 && iteration === 1) {
66
- poolMaxDebounces *= steps;
67
-
68
- log('Found a large number of attributes, increasing timeout to ' + (poolMaxDebounces * POOL_DEBOUNCE / 1000 / 60) + ' minutes')
69
- }
70
-
71
- await new Promise(resolve => setTimeout(resolve, POOL_DEBOUNCE));
72
-
73
- return await awaitPools.wipeAttributes(
74
- databaseId,
75
- collectionId,
76
- iteration + 1
77
- );
78
- },
79
- wipeIndexes: async (databaseId, collectionId, iteration = 1) => {
80
- if (iteration > poolMaxDebounces) {
81
- return false;
82
- }
83
-
84
- const { total } = await databasesListIndexes({
85
- databaseId,
86
- collectionId,
87
- queries: [JSON.stringify({ method: 'limit', values: [1] })],
88
- parseOutput: false
89
- });
90
-
91
- if (total === 0) {
92
- return true;
93
- }
94
-
95
- let steps = Math.max(1, Math.ceil(total / STEP_SIZE));
96
- if (steps > 1 && iteration === 1) {
97
- poolMaxDebounces *= steps;
98
-
99
- log('Found a large number of indexes, increasing timeout to ' + (poolMaxDebounces * POOL_DEBOUNCE / 1000 / 60) + ' minutes')
100
- }
101
-
102
- await new Promise(resolve => setTimeout(resolve, POOL_DEBOUNCE));
103
-
104
- return await awaitPools.wipeIndexes(
105
- databaseId,
106
- collectionId,
107
- iteration + 1
108
- );
109
- },
110
- wipeVariables: async (functionId, iteration = 1) => {
111
- if (iteration > poolMaxDebounces) {
112
- return false;
113
- }
114
-
115
- const { total } = await functionsListVariables({
116
- functionId,
117
- queries: ['limit(1)'],
118
- parseOutput: false
119
- });
120
-
121
- if (total === 0) {
122
- return true;
123
- }
124
-
125
- let steps = Math.max(1, Math.ceil(total / STEP_SIZE));
126
- if (steps > 1 && iteration === 1) {
127
- poolMaxDebounces *= steps;
128
-
129
- log('Found a large number of variables, increasing timeout to ' + (poolMaxDebounces * POOL_DEBOUNCE / 1000 / 60) + ' minutes')
130
- }
131
-
132
- await new Promise(resolve => setTimeout(resolve, POOL_DEBOUNCE));
133
-
134
- return await awaitPools.wipeVariables(
135
- functionId,
136
- iteration + 1
137
- );
138
- },
139
- expectAttributes: async (databaseId, collectionId, attributeKeys, iteration = 1) => {
140
- if (iteration > poolMaxDebounces) {
141
- return false;
142
- }
143
-
144
- let steps = Math.max(1, Math.ceil(attributeKeys.length / STEP_SIZE));
145
- if (steps > 1 && iteration === 1) {
146
- poolMaxDebounces *= steps;
147
-
148
- log('Creating a large number of attributes, increasing timeout to ' + (poolMaxDebounces * POOL_DEBOUNCE / 1000 / 60) + ' minutes')
149
- }
150
-
151
- const { attributes } = await paginate(databasesListAttributes, {
152
- databaseId,
153
- collectionId,
154
- parseOutput: false
155
- }, 100, 'attributes');
156
-
157
- const ready = attributes
158
- .filter(attribute => {
159
- if (attributeKeys.includes(attribute.key)) {
160
- if (['stuck', 'failed'].includes(attribute.status)) {
161
- throw new Error(`Attribute '${attribute.key}' failed!`);
162
- }
163
-
164
- return attribute.status === 'available';
165
- }
166
-
167
- return false;
168
- })
169
- .map(attribute => attribute.key);
170
-
171
- if (ready.length === attributeKeys.length) {
172
- return true;
173
- }
174
-
175
- await new Promise(resolve => setTimeout(resolve, POOL_DEBOUNCE));
176
-
177
- return await awaitPools.expectAttributes(
178
- databaseId,
179
- collectionId,
180
- attributeKeys,
181
- iteration + 1
182
- );
183
- },
184
- expectIndexes: async (databaseId, collectionId, indexKeys, iteration = 1) => {
185
- if (iteration > poolMaxDebounces) {
186
- return false;
187
- }
188
-
189
- let steps = Math.max(1, Math.ceil(indexKeys.length / STEP_SIZE));
190
- if (steps > 1 && iteration === 1) {
191
- poolMaxDebounces *= steps;
192
-
193
- log('Creating a large number of indexes, increasing timeout to ' + (poolMaxDebounces * POOL_DEBOUNCE / 1000 / 60) + ' minutes')
194
- }
195
-
196
- const { indexes } = await paginate(databasesListIndexes, {
197
- databaseId,
198
- collectionId,
199
- parseOutput: false
200
- }, 100, 'indexes');
201
-
202
- const ready = indexes
203
- .filter((index) => {
204
- if (indexKeys.includes(index.key)) {
205
- if (['stuck', 'failed'].includes(index.status)) {
206
- throw new Error(`Index '${index.key}' failed!`);
207
- }
208
-
209
- return index.status === 'available';
210
- }
211
-
212
- return false;
213
- })
214
- .map(index => index.key);
215
-
216
- if (ready.length >= indexKeys.length) {
217
- return true;
218
- }
219
-
220
- await new Promise(resolve => setTimeout(resolve, POOL_DEBOUNCE));
221
-
222
- return await awaitPools.expectIndexes(
223
- databaseId,
224
- collectionId,
225
- indexKeys,
226
- iteration + 1
227
- );
228
- },
229
- }
230
-
231
- const deploy = new Command("deploy")
232
- .description(commandDescriptions['deploy'])
233
- .configureHelp({
234
- helpWidth: process.stdout.columns || 80
235
- })
236
- .action(actionRunner(async (_options, command) => {
237
- command.help()
238
- }));
239
-
240
- const deployFunction = async ({ functionId, all, yes } = {}) => {
241
- let response = {};
242
-
243
- const functionIds = [];
244
-
245
- if (functionId) {
246
- functionIds.push(functionId);
247
- } else if (all) {
248
- const functions = localConfig.getFunctions();
249
- checkDeployConditions(localConfig);
250
- if (functions.length === 0) {
251
- throw new Error("No functions found in the current directory.");
252
- }
253
- functionIds.push(...functions.map((func, idx) => {
254
- return func.$id;
255
- }));
256
- }
257
-
258
- if (functionIds.length <= 0) {
259
- const answers = await inquirer.prompt(questionsDeployFunctions[0]);
260
- functionIds.push(...answers.functions);
261
- }
262
-
263
- let functions = functionIds.map((id) => {
264
- const functions = localConfig.getFunctions();
265
- const func = functions.find((f) => f.$id === id);
266
-
267
- if (!func) {
268
- throw new Error("Function '" + id + "' not found.")
269
- }
270
-
271
- return func;
272
- });
273
-
274
- for (let func of functions) {
275
- log(`Deploying function ${func.name} ( ${func['$id']} )`)
276
-
277
- try {
278
- response = await functionsGet({
279
- functionId: func['$id'],
280
- parseOutput: false,
281
- });
282
-
283
- if (response.runtime !== func.runtime) {
284
- throw new Error(`Runtime missmatch! (local=${func.runtime},remote=${response.runtime}) Please delete remote function or update your appwrite.json`);
285
- }
286
-
287
- response = await functionsUpdate({
288
- functionId: func['$id'],
289
- name: func.name,
290
- execute: func.execute,
291
- events: func.events,
292
- schedule: func.schedule,
293
- timeout: func.timeout,
294
- enabled: func.enabled,
295
- logging: func.logging,
296
- entrypoint: func.entrypoint,
297
- commands: func.commands,
298
- vars: JSON.stringify(response.vars),
299
- parseOutput: false
300
- });
301
- } catch (e) {
302
- if (e.code == 404) {
303
- log(`Function ${func.name} ( ${func['$id']} ) does not exist in the project. Creating ... `);
304
- response = await functionsCreate({
305
- functionId: func.$id || 'unique()',
306
- name: func.name,
307
- runtime: func.runtime,
308
- execute: func.execute,
309
- events: func.events,
310
- schedule: func.schedule,
311
- timeout: func.timeout,
312
- enabled: func.enabled,
313
- logging: func.logging,
314
- entrypoint: func.entrypoint,
315
- commands: func.commands,
316
- vars: JSON.stringify(func.vars),
317
- parseOutput: false
318
- });
319
-
320
- localConfig.updateFunction(func['$id'], {
321
- "$id": response['$id'],
322
- });
323
-
324
- func["$id"] = response['$id'];
325
- log(`Function ${func.name} created.`);
326
- } else {
327
- throw e;
328
- }
329
- }
330
-
331
- if (func.variables) {
332
- // Delete existing variables
333
-
334
- const { total } = await functionsListVariables({
335
- functionId: func['$id'],
336
- queries: [JSON.stringify({ method: 'limit', values: [1] })],
337
- parseOutput: false
338
- });
339
-
340
- let deployVariables = yes;
341
-
342
- if (total === 0) {
343
- deployVariables = true;
344
- } else if (total > 0 && !yes) {
345
- const variableAnswers = await inquirer.prompt(questionsDeployFunctions[1])
346
- deployVariables = variableAnswers.override.toLowerCase() === "yes";
347
- }
348
-
349
- if (!deployVariables) {
350
- log(`Skipping variables for ${func.name} ( ${func['$id']} )`);
351
- } else {
352
- log(`Deploying variables for ${func.name} ( ${func['$id']} )`);
353
-
354
- const { variables } = await paginate(functionsListVariables, {
355
- functionId: func['$id'],
356
- parseOutput: false
357
- }, 100, 'variables');
358
-
359
- await Promise.all(variables.map(async variable => {
360
- await functionsDeleteVariable({
361
- functionId: func['$id'],
362
- variableId: variable['$id'],
363
- parseOutput: false
364
- });
365
- }));
366
-
367
- let result = await awaitPools.wipeVariables(func['$id']);
368
- if (!result) {
369
- throw new Error("Variable deletion timed out.");
370
- }
371
-
372
- // Deploy local variables
373
- await Promise.all(Object.keys(func.variables).map(async localVariableKey => {
374
- await functionsCreateVariable({
375
- functionId: func['$id'],
376
- key: localVariableKey,
377
- value: func.variables[localVariableKey],
378
- parseOutput: false
379
- });
380
- }));
381
- }
382
- }
383
-
384
- // Create tag
385
- if (!func.entrypoint) {
386
- const answers = await inquirer.prompt(questionsGetEntrypoint)
387
- func.entrypoint = answers.entrypoint;
388
- localConfig.updateFunction(func['$id'], func);
389
- }
390
-
391
- try {
392
- response = await functionsCreateDeployment({
393
- functionId: func['$id'],
394
- entrypoint: func.entrypoint,
395
- commands: func.commands,
396
- code: func.path,
397
- activate: true,
398
- parseOutput: false
399
- })
400
-
401
- success(`Deployed ${func.name} ( ${func['$id']} )`);
402
-
403
- } catch (e) {
404
- switch (e.code) {
405
- case 'ENOENT':
406
- error(`Function ${func.name} ( ${func['$id']} ) not found in the current directory. Skipping ...`);
407
- break;
408
- default:
409
- throw e;
410
- }
411
- }
412
- }
413
-
414
- success(`Deployed ${functions.length} functions`);
415
- }
416
-
417
- const createAttribute = async (databaseId, collectionId, attribute) => {
418
- switch (attribute.type) {
419
- case 'string':
420
- switch (attribute.format) {
421
- case 'email':
422
- return await databasesCreateEmailAttribute({
423
- databaseId,
424
- collectionId,
425
- key: attribute.key,
426
- required: attribute.required,
427
- xdefault: attribute.default,
428
- array: attribute.array,
429
- parseOutput: false
430
- })
431
- case 'url':
432
- return await databasesCreateUrlAttribute({
433
- databaseId,
434
- collectionId,
435
- key: attribute.key,
436
- required: attribute.required,
437
- xdefault: attribute.default,
438
- array: attribute.array,
439
- parseOutput: false
440
- })
441
- case 'ip':
442
- return await databasesCreateIpAttribute({
443
- databaseId,
444
- collectionId,
445
- key: attribute.key,
446
- required: attribute.required,
447
- xdefault: attribute.default,
448
- array: attribute.array,
449
- parseOutput: false
450
- })
451
- case 'enum':
452
- return await databasesCreateEnumAttribute({
453
- databaseId,
454
- collectionId,
455
- key: attribute.key,
456
- elements: attribute.elements,
457
- required: attribute.required,
458
- xdefault: attribute.default,
459
- array: attribute.array,
460
- parseOutput: false
461
- })
462
- default:
463
- return await databasesCreateStringAttribute({
464
- databaseId,
465
- collectionId,
466
- key: attribute.key,
467
- size: attribute.size,
468
- required: attribute.required,
469
- xdefault: attribute.default,
470
- array: attribute.array,
471
- parseOutput: false
472
- })
473
-
474
- }
475
- case 'integer':
476
- return await databasesCreateIntegerAttribute({
477
- databaseId,
478
- collectionId,
479
- key: attribute.key,
480
- required: attribute.required,
481
- min: attribute.min,
482
- max: attribute.max,
483
- xdefault: attribute.default,
484
- array: attribute.array,
485
- parseOutput: false
486
- })
487
- case 'double':
488
- return databasesCreateFloatAttribute({
489
- databaseId,
490
- collectionId,
491
- key: attribute.key,
492
- required: attribute.required,
493
- min: attribute.min,
494
- max: attribute.max,
495
- xdefault: attribute.default,
496
- array: attribute.array,
497
- parseOutput: false
498
- })
499
- case 'boolean':
500
- return databasesCreateBooleanAttribute({
501
- databaseId,
502
- collectionId,
503
- key: attribute.key,
504
- required: attribute.required,
505
- xdefault: attribute.default,
506
- array: attribute.array,
507
- parseOutput: false
508
- })
509
- case 'datetime':
510
- return databasesCreateDatetimeAttribute({
511
- databaseId,
512
- collectionId,
513
- key: attribute.key,
514
- required: attribute.required,
515
- xdefault: attribute.default,
516
- array: attribute.array,
517
- parseOutput: false
518
- })
519
- case 'relationship':
520
- return databasesCreateRelationshipAttribute({
521
- databaseId,
522
- collectionId,
523
- relatedCollectionId: attribute.relatedCollection,
524
- type: attribute.relationType,
525
- twoWay: attribute.twoWay,
526
- key: attribute.key,
527
- twoWayKey: attribute.twoWayKey,
528
- onDelete: attribute.onDelete,
529
- parseOutput: false
530
- })
531
- }
532
- }
533
-
534
- const deployCollection = async ({ all, yes } = {}) => {
535
- let response = {};
536
-
537
- const collections = [];
538
-
539
- if (all) {
540
- checkDeployConditions(localConfig);
541
- if (localConfig.getCollections().length === 0) {
542
- throw new Error("No collections found in the current directory. Run `appwrite init collection` to fetch all your collections.");
543
- }
544
- collections.push(...localConfig.getCollections());
545
- } else {
546
- const answers = await inquirer.prompt(questionsDeployCollections[0])
547
- const configCollections = new Map();
548
- localConfig.getCollections().forEach((c) => {
549
- configCollections.set(`${c['databaseId']}|${c['$id']}`, c);
550
- });
551
- answers.collections.forEach((a) => {
552
- const collection = configCollections.get(a);
553
- collections.push(collection);
554
- })
555
- }
556
-
557
- for (let collection of collections) {
558
- log(`Deploying collection ${collection.name} ( ${collection['databaseId']} - ${collection['$id']} )`)
559
-
560
- let databaseId;
561
-
562
- const localDatabase = localConfig.getDatabase(collection.databaseId);
563
-
564
- try {
565
- const database = await databasesGet({
566
- databaseId: collection.databaseId,
567
- parseOutput: false,
568
- });
569
-
570
- databaseId = database.$id;
571
-
572
- if (database.name !== (localDatabase.name ?? collection.databaseId)) {
573
- await databasesUpdate({
574
- databaseId: collection.databaseId,
575
- name: localDatabase.name ?? collection.databaseId,
576
- parseOutput: false
577
- })
578
-
579
- success(`Updated ${localDatabase.name} ( ${collection.databaseId} )`);
580
- }
581
- } catch (err) {
582
- log(`Database ${collection.databaseId} not found. Creating it now...`);
583
-
584
- const database = await databasesCreate({
585
- databaseId: collection.databaseId,
586
- name: localDatabase.name ?? collection.databaseId,
587
- parseOutput: false,
588
- });
589
-
590
- databaseId = database.$id;
591
- }
592
-
593
- try {
594
- response = await databasesGetCollection({
595
- databaseId,
596
- collectionId: collection['$id'],
597
- parseOutput: false,
598
- })
599
-
600
- log(`Collection ${collection.name} ( ${collection['$id']} ) already exists.`);
601
-
602
- if (!yes) {
603
- const answers = await inquirer.prompt(questionsDeployCollections[1])
604
- if (answers.override.toLowerCase() !== "yes") {
605
- log(`Received "${answers.override}". Skipping ${collection.name} ( ${collection['$id']} )`);
606
- continue;
607
- }
608
- }
609
-
610
- log(`Deleting indexes and attributes ... `);
611
-
612
- const { indexes } = await paginate(databasesListIndexes, {
613
- databaseId,
614
- collectionId: collection['$id'],
615
- parseOutput: false
616
- }, 100, 'indexes');
617
-
618
- await Promise.all(indexes.map(async index => {
619
- await databasesDeleteIndex({
620
- databaseId,
621
- collectionId: collection['$id'],
622
- key: index.key,
623
- parseOutput: false
624
- });
625
- }));
626
-
627
- let result = await awaitPools.wipeIndexes(databaseId, collection['$id']);
628
- if (!result) {
629
- throw new Error("Index deletion timed out.");
630
- }
631
-
632
- const { attributes } = await paginate(databasesListAttributes, {
633
- databaseId,
634
- collectionId: collection['$id'],
635
- parseOutput: false
636
- }, 100, 'attributes');
637
-
638
- await Promise.all(attributes.map(async attribute => {
639
- await databasesDeleteAttribute({
640
- databaseId,
641
- collectionId: collection['$id'],
642
- key: attribute.key,
643
- parseOutput: false
644
- });
645
- }));
646
-
647
- const deleteAttributesPoolStatus = await awaitPools.wipeAttributes(databaseId, collection['$id']);
648
- if (!deleteAttributesPoolStatus) {
649
- throw new Error("Attribute deletion timed out.");
650
- }
651
-
652
- await databasesUpdateCollection({
653
- databaseId,
654
- collectionId: collection['$id'],
655
- name: collection.name,
656
- documentSecurity: collection.documentSecurity,
657
- permissions: collection['$permissions'],
658
- enabled: collection.enabled,
659
- parseOutput: false
660
- })
661
- } catch (e) {
662
- if (e.code == 404) {
663
- log(`Collection ${collection.name} does not exist in the project. Creating ... `);
664
- response = await databasesCreateCollection({
665
- databaseId,
666
- collectionId: collection['$id'],
667
- name: collection.name,
668
- documentSecurity: collection.documentSecurity,
669
- permissions: collection['$permissions'],
670
- parseOutput: false
671
- })
672
-
673
- } else {
674
- throw e;
675
- }
676
- }
677
-
678
- // Create all non-relationship attributes first
679
- const attributes = collection.attributes.filter(attribute => attribute.type !== 'relationship');
680
-
681
- await Promise.all(attributes.map(attribute => {
682
- return createAttribute(databaseId, collection['$id'], attribute);
683
- }));
684
-
685
- let result = await awaitPools.expectAttributes(
686
- databaseId,
687
- collection['$id'],
688
- attributes.map(attribute => attribute.key)
689
- );
690
-
691
- if (!result) {
692
- throw new Error("Attribute creation timed out.");
693
- }
694
-
695
- success(`Created ${attributes.length} non-relationship attributes`);
696
-
697
- log(`Creating indexes ...`)
698
-
699
- await Promise.all(collection.indexes.map(async index => {
700
- await databasesCreateIndex({
701
- databaseId,
702
- collectionId: collection['$id'],
703
- key: index.key,
704
- type: index.type,
705
- attributes: index.attributes,
706
- orders: index.orders,
707
- parseOutput: false
708
- });
709
- }));
710
-
711
- result = await awaitPools.expectIndexes(
712
- databaseId,
713
- collection['$id'],
714
- collection.indexes.map(attribute => attribute.key)
715
- );
716
-
717
- if (!result) {
718
- throw new Error("Index creation timed out.");
719
- }
720
-
721
- success(`Created ${collection.indexes.length} indexes`);
722
-
723
- success(`Deployed ${collection.name} ( ${collection['$id']} )`);
724
- }
725
-
726
- // Create the relationship attributes
727
- for (let collection of collections) {
728
- const relationships = collection.attributes.filter(attribute =>
729
- attribute.type === 'relationship' && attribute.side === 'parent'
730
- );
731
-
732
- if (relationships.length === 0) {
733
- continue;
734
- }
735
-
736
- log(`Deploying relationships for collection ${collection.name} ( ${collection['$id']} )`);
737
-
738
- await Promise.all(relationships.map(attribute => {
739
- return createAttribute(collection['databaseId'], collection['$id'], attribute);
740
- }));
741
-
742
- let result = await awaitPools.expectAttributes(
743
- collection['databaseId'],
744
- collection['$id'],
745
- relationships.map(attribute => attribute.key)
746
- );
747
-
748
- if (!result) {
749
- throw new Error("Attribute creation timed out.");
750
- }
751
-
752
- success(`Created ${relationships.length} relationship attributes`);
753
- }
754
- }
755
-
756
- const deployBucket = async ({ all, yes } = {}) => {
757
- let response = {};
758
-
759
- let bucketIds = [];
760
- const configBuckets = localConfig.getBuckets();
761
-
762
- if (all) {
763
- checkDeployConditions(localConfig);
764
- bucketIds.push(...configBuckets.map((b) => b.$id));
765
- }
766
-
767
- if (bucketIds.length === 0) {
768
- const answers = await inquirer.prompt(questionsDeployBuckets[0])
769
- bucketIds.push(...answers.buckets);
770
- }
771
-
772
- let buckets = [];
773
-
774
- for (const bucketId of bucketIds) {
775
- const idBuckets = configBuckets.filter((b) => b.$id === bucketId);
776
- buckets.push(...idBuckets);
777
- }
778
-
779
- for (let bucket of buckets) {
780
- log(`Deploying bucket ${bucket.name} ( ${bucket['$id']} )`)
781
-
782
- try {
783
- response = await storageGetBucket({
784
- bucketId: bucket['$id'],
785
- parseOutput: false,
786
- })
787
- log(`Bucket ${bucket.name} ( ${bucket['$id']} ) already exists.`);
788
-
789
- if (!yes) {
790
- const answers = await inquirer.prompt(questionsDeployBuckets[1])
791
- if (answers.override.toLowerCase() !== "yes") {
792
- log(`Received "${answers.override}". Skipping ${bucket.name} ( ${bucket['$id']} )`);
793
- continue;
794
- }
795
- }
796
-
797
- log(`Updating bucket ...`)
798
-
799
- await storageUpdateBucket({
800
- bucketId: bucket['$id'],
801
- name: bucket.name,
802
- permissions: bucket['$permissions'],
803
- fileSecurity: bucket.fileSecurity,
804
- enabled: bucket.enabled,
805
- maximumFileSize: bucket.maximumFileSize,
806
- allowedFileExtensions: bucket.allowedFileExtensions,
807
- compression: bucket.compression,
808
- encryption: bucket.encryption,
809
- antivirus: bucket.antivirus,
810
- compression: bucket.compression,
811
- parseOutput: false
812
- });
813
-
814
- success(`Deployed ${bucket.name} ( ${bucket['$id']} )`);
815
- } catch (e) {
816
- if (e.code == 404) {
817
- log(`Bucket ${bucket.name} does not exist in the project. Creating ... `);
818
-
819
- response = await storageCreateBucket({
820
- bucketId: bucket['$id'],
821
- name: bucket.name,
822
- permissions: bucket['$permissions'],
823
- fileSecurity: bucket.fileSecurity,
824
- enabled: bucket.enabled,
825
- maximumFileSize: bucket.maximumFileSize,
826
- allowedFileExtensions: bucket.allowedFileExtensions,
827
- compression: bucket.compression,
828
- encryption: bucket.encryption,
829
- antivirus: bucket.antivirus,
830
- parseOutput: false
831
- })
832
-
833
- success(`Deployed ${bucket.name} ( ${bucket['$id']} )`);
834
- } else {
835
- throw e;
836
- }
837
- }
838
- }
839
- }
840
-
841
- const deployTeam = async ({ all, yes } = {}) => {
842
- let response = {};
843
-
844
- let teamIds = [];
845
- const configTeams = localConfig.getTeams();
846
-
847
- if (all) {
848
- checkDeployConditions(localConfig);
849
- teamIds.push(...configTeams.map((t) => t.$id));
850
- }
851
-
852
- if (teamIds.length === 0) {
853
- const answers = await inquirer.prompt(questionsDeployTeams[0])
854
- teamIds.push(...answers.teams);
855
- }
856
-
857
- let teams = [];
858
-
859
- for (const teamId of teamIds) {
860
- const idTeams = configTeams.filter((t) => t.$id === teamId);
861
- teams.push(...idTeams);
862
- }
863
-
864
- for (let team of teams) {
865
- log(`Deploying team ${team.name} ( ${team['$id']} )`)
866
-
867
- try {
868
- response = await teamsGet({
869
- teamId: team['$id'],
870
- parseOutput: false,
871
- })
872
- log(`Team ${team.name} ( ${team['$id']} ) already exists.`);
873
-
874
- if (!yes) {
875
- const answers = await inquirer.prompt(questionsDeployTeams[1])
876
- if (answers.override.toLowerCase() !== "yes") {
877
- log(`Received "${answers.override}". Skipping ${team.name} ( ${team['$id']} )`);
878
- continue;
879
- }
880
- }
881
-
882
- log(`Updating team ...`)
883
-
884
- await teamsUpdateName({
885
- teamId: team['$id'],
886
- name: team.name,
887
- parseOutput: false
888
- });
889
-
890
- success(`Deployed ${team.name} ( ${team['$id']} )`);
891
- } catch (e) {
892
- if (e.code == 404) {
893
- log(`Team ${team.name} does not exist in the project. Creating ... `);
894
-
895
- response = await teamsCreate({
896
- teamId: team['$id'],
897
- name: team.name,
898
- parseOutput: false
899
- })
900
-
901
- success(`Deployed ${team.name} ( ${team['$id']} )`);
902
- } else {
903
- throw e;
904
- }
905
- }
906
- }
907
- }
908
-
909
- deploy
910
- .command("function")
911
- .description("Deploy functions in the current directory.")
912
- .option(`--functionId <functionId>`, `Function ID`)
913
- .option(`--all`, `Flag to deploy all functions`)
914
- .option(`--yes`, `Flag to confirm all warnings`)
915
- .action(actionRunner(deployFunction));
916
-
917
- deploy
918
- .command("collection")
919
- .description("Deploy collections in the current project.")
920
- .option(`--all`, `Flag to deploy all collections`)
921
- .option(`--yes`, `Flag to confirm all warnings`)
922
- .action(actionRunner(deployCollection));
923
-
924
- deploy
925
- .command("bucket")
926
- .description("Deploy buckets in the current project.")
927
- .option(`--all`, `Flag to deploy all buckets`)
928
- .option(`--yes`, `Flag to confirm all warnings`)
929
- .action(actionRunner(deployBucket));
930
-
931
- deploy
932
- .command("team")
933
- .description("Deploy teams in the current project.")
934
- .option(`--all`, `Flag to deploy all teams`)
935
- .option(`--yes`, `Flag to confirm all warnings`)
936
- .action(actionRunner(deployTeam));
937
-
938
- module.exports = {
939
- deploy
940
- }