appwrite-cli 1.1.1 → 2.0.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/Formula/appwrite.rb +1 -1
- package/LICENSE.md +2 -2
- package/README.md +4 -4
- package/docs/examples/account/create-phone-session.md +1 -1
- package/docs/examples/account/create.md +1 -1
- package/docs/examples/account/update-password.md +1 -1
- package/docs/examples/account/update-phone.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/{retry-build.md → create-build.md} +1 -1
- package/docs/examples/functions/create.md +1 -1
- package/docs/examples/functions/update.md +1 -1
- package/docs/examples/graphql/mutation.md +2 -0
- package/docs/examples/graphql/query.md +2 -0
- package/docs/examples/projects/create.md +1 -0
- package/docs/examples/projects/update-auth-duration.md +3 -0
- 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/projects/update-auth-sessions-limit.md +3 -0
- package/docs/examples/projects/update-o-auth2.md +1 -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/docs/examples/users/update-phone.md +1 -1
- package/index.js +16 -1
- package/install.ps1 +2 -2
- package/install.sh +1 -1
- package/lib/client.js +7 -7
- package/lib/commands/account.js +46 -11
- package/lib/commands/avatars.js +3 -1
- package/lib/commands/console.js +44 -0
- package/lib/commands/databases.js +735 -109
- package/lib/commands/deploy.js +350 -141
- package/lib/commands/functions.js +44 -16
- package/lib/commands/generic.js +15 -3
- package/lib/commands/graphql.js +85 -0
- package/lib/commands/health.js +3 -1
- package/lib/commands/init.js +224 -162
- package/lib/commands/locale.js +3 -1
- package/lib/commands/projects.js +223 -9
- package/lib/commands/storage.js +43 -13
- package/lib/commands/teams.js +107 -19
- package/lib/commands/users.js +62 -11
- package/lib/config.js +122 -5
- package/lib/parser.js +7 -2
- package/lib/questions.js +311 -257
- package/package.json +1 -1
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 { 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,21 @@ 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");
|
|
34
|
+
const {
|
|
35
|
+
teamsGet,
|
|
36
|
+
teamsUpdate,
|
|
37
|
+
teamsCreate
|
|
38
|
+
} = require("./teams");
|
|
28
39
|
|
|
29
40
|
const POOL_DEBOUNCE = 2000; // in milliseconds
|
|
30
41
|
const POOL_MAX_DEBOUNCES = 30;
|
|
@@ -39,7 +50,7 @@ const awaitPools = {
|
|
|
39
50
|
const { attributes: remoteAttributes } = await databasesListAttributes({
|
|
40
51
|
databaseId,
|
|
41
52
|
collectionId,
|
|
42
|
-
queries: [
|
|
53
|
+
queries: ['limit(100)'],
|
|
43
54
|
parseOutput: false
|
|
44
55
|
});
|
|
45
56
|
|
|
@@ -59,7 +70,7 @@ const awaitPools = {
|
|
|
59
70
|
const { indexes: remoteIndexes } = await databasesListIndexes({
|
|
60
71
|
databaseId,
|
|
61
72
|
collectionId,
|
|
62
|
-
queries: [
|
|
73
|
+
queries: ['limit(100)'],
|
|
63
74
|
parseOutput: false
|
|
64
75
|
});
|
|
65
76
|
|
|
@@ -79,7 +90,7 @@ const awaitPools = {
|
|
|
79
90
|
const { attributes: remoteAttributes } = await databasesListAttributes({
|
|
80
91
|
databaseId,
|
|
81
92
|
collectionId,
|
|
82
|
-
queries: [
|
|
93
|
+
queries: ['limit(100)'],
|
|
83
94
|
parseOutput: false
|
|
84
95
|
});
|
|
85
96
|
|
|
@@ -111,7 +122,7 @@ const awaitPools = {
|
|
|
111
122
|
const { indexes: remoteIndexes } = await databasesListIndexes({
|
|
112
123
|
databaseId,
|
|
113
124
|
collectionId,
|
|
114
|
-
queries: [
|
|
125
|
+
queries: ['limit(100)'],
|
|
115
126
|
parseOutput: false
|
|
116
127
|
});
|
|
117
128
|
|
|
@@ -138,6 +149,9 @@ const awaitPools = {
|
|
|
138
149
|
|
|
139
150
|
const deploy = new Command("deploy")
|
|
140
151
|
.description(commandDescriptions['deploy'])
|
|
152
|
+
.configureHelp({
|
|
153
|
+
helpWidth: process.stdout.columns || 80
|
|
154
|
+
})
|
|
141
155
|
.action(actionRunner(async (_options, command) => {
|
|
142
156
|
command.help()
|
|
143
157
|
}));
|
|
@@ -147,9 +161,9 @@ const deployFunction = async ({ functionId, all, yes } = {}) => {
|
|
|
147
161
|
|
|
148
162
|
const functionIds = [];
|
|
149
163
|
|
|
150
|
-
if(functionId) {
|
|
164
|
+
if (functionId) {
|
|
151
165
|
functionIds.push(functionId);
|
|
152
|
-
} else if(all) {
|
|
166
|
+
} else if (all) {
|
|
153
167
|
const functions = localConfig.getFunctions();
|
|
154
168
|
if (functions.length === 0) {
|
|
155
169
|
throw new Error("No functions found in the current directory.");
|
|
@@ -159,22 +173,22 @@ const deployFunction = async ({ functionId, all, yes } = {}) => {
|
|
|
159
173
|
}));
|
|
160
174
|
}
|
|
161
175
|
|
|
162
|
-
if(functionIds.length <= 0) {
|
|
176
|
+
if (functionIds.length <= 0) {
|
|
163
177
|
const answers = await inquirer.prompt(questionsDeployFunctions[0]);
|
|
164
178
|
functionIds.push(...answers.functions);
|
|
165
179
|
}
|
|
166
180
|
|
|
167
181
|
let functions = functionIds.map((id) => {
|
|
168
|
-
|
|
169
|
-
|
|
182
|
+
const functions = localConfig.getFunctions();
|
|
183
|
+
const func = functions.find((f) => f.$id === id);
|
|
170
184
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
185
|
+
if (!func) {
|
|
186
|
+
throw new Error("Function '" + id + "' not found.")
|
|
187
|
+
}
|
|
174
188
|
|
|
175
|
-
|
|
189
|
+
return func;
|
|
176
190
|
});
|
|
177
|
-
|
|
191
|
+
|
|
178
192
|
for (let func of functions) {
|
|
179
193
|
log(`Deploying function ${func.name} ( ${func['$id']} )`)
|
|
180
194
|
|
|
@@ -184,50 +198,10 @@ const deployFunction = async ({ functionId, all, yes } = {}) => {
|
|
|
184
198
|
parseOutput: false,
|
|
185
199
|
});
|
|
186
200
|
|
|
187
|
-
if(response.runtime !== func.runtime) {
|
|
201
|
+
if (response.runtime !== func.runtime) {
|
|
188
202
|
throw new Error(`Runtime missmatch! (local=${func.runtime},remote=${response.runtime}) Please delete remote function or update your appwrite.json`);
|
|
189
203
|
}
|
|
190
204
|
|
|
191
|
-
if(func.variables) {
|
|
192
|
-
// Delete existing variables
|
|
193
|
-
|
|
194
|
-
// TODO: Pagination?
|
|
195
|
-
const { variables: remoteVariables } = await functionsListVariables({
|
|
196
|
-
functionId: func['$id'],
|
|
197
|
-
queries: [ 'limit(100)' ],
|
|
198
|
-
parseOutput: false
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
if(remoteVariables.length > 0) {
|
|
202
|
-
if(!yes) {
|
|
203
|
-
const variableAnswers = await inquirer.prompt(questionsDeployFunctions[1])
|
|
204
|
-
|
|
205
|
-
if (variableAnswers.override !== "YES") {
|
|
206
|
-
log(`Received "${variableAnswers.override}". Skipping ${func.name} ( ${func['$id']} )`);
|
|
207
|
-
continue;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
await Promise.all(remoteVariables.map(async remoteVariable => {
|
|
212
|
-
await functionsDeleteVariable({
|
|
213
|
-
functionId: func['$id'],
|
|
214
|
-
variableId: remoteVariable['$id'],
|
|
215
|
-
parseOutput: false
|
|
216
|
-
});
|
|
217
|
-
}));
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// Deploy local variables
|
|
221
|
-
await Promise.all(Object.keys(func.variables).map(async localVariableKey => {
|
|
222
|
-
await functionsCreateVariable({
|
|
223
|
-
functionId: func['$id'],
|
|
224
|
-
key: localVariableKey,
|
|
225
|
-
value: func.variables[localVariableKey],
|
|
226
|
-
parseOutput: false
|
|
227
|
-
});
|
|
228
|
-
}));
|
|
229
|
-
}
|
|
230
|
-
|
|
231
205
|
response = await functionsUpdate({
|
|
232
206
|
functionId: func['$id'],
|
|
233
207
|
name: func.name,
|
|
@@ -264,6 +238,49 @@ const deployFunction = async ({ functionId, all, yes } = {}) => {
|
|
|
264
238
|
}
|
|
265
239
|
}
|
|
266
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
|
+
|
|
267
284
|
// Create tag
|
|
268
285
|
if (!func.entrypoint) {
|
|
269
286
|
answers = await inquirer.prompt(questionsGetEntrypoint)
|
|
@@ -292,6 +309,8 @@ const deployFunction = async ({ functionId, all, yes } = {}) => {
|
|
|
292
309
|
}
|
|
293
310
|
}
|
|
294
311
|
}
|
|
312
|
+
|
|
313
|
+
success(`Deployed ${functions.length} functions`);
|
|
295
314
|
}
|
|
296
315
|
|
|
297
316
|
const createAttribute = async (databaseId, collectionId, attribute) => {
|
|
@@ -396,50 +415,69 @@ const createAttribute = async (databaseId, collectionId, attribute) => {
|
|
|
396
415
|
array: attribute.array,
|
|
397
416
|
parseOutput: false
|
|
398
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
|
+
})
|
|
399
430
|
}
|
|
400
431
|
}
|
|
401
432
|
|
|
402
433
|
const deployCollection = async ({ all, yes } = {}) => {
|
|
403
434
|
let response = {};
|
|
404
435
|
|
|
405
|
-
|
|
406
|
-
const configCollections = localConfig.getCollections();
|
|
436
|
+
const collections = [];
|
|
407
437
|
|
|
408
|
-
if(all) {
|
|
409
|
-
if (
|
|
438
|
+
if (all) {
|
|
439
|
+
if (localConfig.getCollections().length === 0) {
|
|
410
440
|
throw new Error("No collections found in the current directory. Run `appwrite init collection` to fetch all your collections.");
|
|
411
441
|
}
|
|
412
|
-
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
const idCollections = configCollections.filter((c) => c.$id === collectionId);
|
|
424
|
-
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
|
+
})
|
|
425
453
|
}
|
|
426
454
|
|
|
427
455
|
for (let collection of collections) {
|
|
428
|
-
log(`Deploying collection ${collection.name} ( ${collection['$id']} )`)
|
|
456
|
+
log(`Deploying collection ${collection.name} ( ${collection['databaseId']} - ${collection['$id']} )`)
|
|
429
457
|
|
|
430
458
|
let databaseId;
|
|
431
459
|
|
|
460
|
+
const localDatabase = localConfig.getDatabase(collection.databaseId);
|
|
461
|
+
|
|
432
462
|
try {
|
|
433
463
|
const database = await databasesGet({
|
|
434
464
|
databaseId: collection.databaseId,
|
|
435
465
|
parseOutput: false,
|
|
436
466
|
});
|
|
437
467
|
databaseId = database.$id;
|
|
438
|
-
|
|
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) {
|
|
439
477
|
log(`Database ${collection.databaseId} not found. Creating it now...`);
|
|
440
478
|
const database = await databasesCreate({
|
|
441
479
|
databaseId: collection.databaseId,
|
|
442
|
-
name: collection.databaseId,
|
|
480
|
+
name: localDatabase.name ?? collection.databaseId,
|
|
443
481
|
parseOutput: false,
|
|
444
482
|
});
|
|
445
483
|
databaseId = database.$id;
|
|
@@ -453,7 +491,7 @@ const deployCollection = async ({ all, yes } = {}) => {
|
|
|
453
491
|
})
|
|
454
492
|
log(`Collection ${collection.name} ( ${collection['$id']} ) already exists.`);
|
|
455
493
|
|
|
456
|
-
if(!yes) {
|
|
494
|
+
if (!yes) {
|
|
457
495
|
answers = await inquirer.prompt(questionsDeployCollections[1])
|
|
458
496
|
if (answers.override !== "YES") {
|
|
459
497
|
log(`Received "${answers.override}". Skipping ${collection.name} ( ${collection['$id']} )`);
|
|
@@ -461,13 +499,13 @@ const deployCollection = async ({ all, yes } = {}) => {
|
|
|
461
499
|
}
|
|
462
500
|
}
|
|
463
501
|
|
|
464
|
-
log(`
|
|
502
|
+
log(`Deleting indexes and attributes ... `);
|
|
465
503
|
|
|
466
504
|
// TODO: Pagination?
|
|
467
505
|
const { indexes: remoteIndexes } = await databasesListIndexes({
|
|
468
506
|
databaseId,
|
|
469
507
|
collectionId: collection['$id'],
|
|
470
|
-
queries: [
|
|
508
|
+
queries: ['limit(100)'],
|
|
471
509
|
parseOutput: false
|
|
472
510
|
});
|
|
473
511
|
|
|
@@ -489,10 +527,10 @@ const deployCollection = async ({ all, yes } = {}) => {
|
|
|
489
527
|
const { attributes: remoteAttributes } = await databasesListAttributes({
|
|
490
528
|
databaseId,
|
|
491
529
|
collectionId: collection['$id'],
|
|
492
|
-
queries: [
|
|
530
|
+
queries: ['limit(100)'],
|
|
493
531
|
parseOutput: false
|
|
494
532
|
});
|
|
495
|
-
|
|
533
|
+
|
|
496
534
|
await Promise.all(remoteAttributes.map(async attribute => {
|
|
497
535
|
await databasesDeleteAttribute({
|
|
498
536
|
databaseId,
|
|
@@ -507,38 +545,15 @@ const deployCollection = async ({ all, yes } = {}) => {
|
|
|
507
545
|
throw new Error("Attribute deletion did not finish for too long.");
|
|
508
546
|
}
|
|
509
547
|
|
|
510
|
-
await
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
success(`Created ${collection.attributes.length} attributes`);
|
|
521
|
-
|
|
522
|
-
log(`Creating indexes ...`)
|
|
523
|
-
await Promise.all(collection.indexes.map(async index => {
|
|
524
|
-
await databasesCreateIndex({
|
|
525
|
-
databaseId,
|
|
526
|
-
collectionId: collection['$id'],
|
|
527
|
-
key: index.key,
|
|
528
|
-
type: index.type,
|
|
529
|
-
attributes: index.attributes,
|
|
530
|
-
orders: index.orders,
|
|
531
|
-
parseOutput: false
|
|
532
|
-
});
|
|
533
|
-
}));
|
|
534
|
-
|
|
535
|
-
const indexKeys = collection.indexes.map(attribute => attribute.key);
|
|
536
|
-
const indexPoolStatus = await awaitPools.expectIndexes(databaseId, collection['$id'], indexKeys);
|
|
537
|
-
if (!indexPoolStatus) {
|
|
538
|
-
throw new Error("Index creation did not finish for too long.");
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
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
|
+
})
|
|
542
557
|
} catch (e) {
|
|
543
558
|
if (e.code == 404) {
|
|
544
559
|
log(`Collection ${collection.name} does not exist in the project. Creating ... `);
|
|
@@ -551,41 +566,221 @@ const deployCollection = async ({ all, yes } = {}) => {
|
|
|
551
566
|
parseOutput: false
|
|
552
567
|
})
|
|
553
568
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
569
|
+
} else {
|
|
570
|
+
throw e;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
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
|
+
}));
|
|
579
|
+
|
|
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
|
+
}
|
|
585
|
+
|
|
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;
|
|
617
|
+
|
|
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
|
+
}
|
|
558
633
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
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;
|
|
563
674
|
}
|
|
675
|
+
}
|
|
564
676
|
|
|
565
|
-
|
|
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
|
+
});
|
|
566
693
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
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
|
+
})
|
|
712
|
+
|
|
713
|
+
success(`Deployed ${bucket.name} ( ${bucket['$id']} )`);
|
|
714
|
+
} else {
|
|
715
|
+
throw e;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
const deployTeam = async ({ all, yes } = {}) => {
|
|
722
|
+
let response = {};
|
|
723
|
+
|
|
724
|
+
let teamIds = [];
|
|
725
|
+
const configTeams = localConfig.getTeams();
|
|
726
|
+
|
|
727
|
+
if (all) {
|
|
728
|
+
if (configTeams.length === 0) {
|
|
729
|
+
throw new Error("No teams found in the current directory. Run `appwrite init team` to fetch all your teams.");
|
|
730
|
+
}
|
|
731
|
+
teamIds.push(...configTeams.map((t) => t.$id));
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
if (teamIds.length === 0) {
|
|
735
|
+
let answers = await inquirer.prompt(questionsDeployTeams[0])
|
|
736
|
+
teamIds.push(...answers.teams);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
let teams = [];
|
|
740
|
+
|
|
741
|
+
for (const teamId of teamIds) {
|
|
742
|
+
const idTeams = configTeams.filter((t) => t.$id === teamId);
|
|
743
|
+
teams.push(...idTeams);
|
|
744
|
+
}
|
|
579
745
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
746
|
+
for (let team of teams) {
|
|
747
|
+
log(`Deploying team ${team.name} ( ${team['$id']} )`)
|
|
748
|
+
|
|
749
|
+
try {
|
|
750
|
+
response = await teamsGet({
|
|
751
|
+
teamId: team['$id'],
|
|
752
|
+
parseOutput: false,
|
|
753
|
+
})
|
|
754
|
+
log(`Team ${team.name} ( ${team['$id']} ) already exists.`);
|
|
755
|
+
|
|
756
|
+
if (!yes) {
|
|
757
|
+
answers = await inquirer.prompt(questionsDeployTeams[1])
|
|
758
|
+
if (answers.override !== "YES") {
|
|
759
|
+
log(`Received "${answers.override}". Skipping ${team.name} ( ${team['$id']} )`);
|
|
760
|
+
continue;
|
|
584
761
|
}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
log(`Updating team ...`)
|
|
585
765
|
|
|
586
|
-
|
|
766
|
+
await teamsUpdate({
|
|
767
|
+
teamId: team['$id'],
|
|
768
|
+
name: team.name,
|
|
769
|
+
parseOutput: false
|
|
770
|
+
});
|
|
587
771
|
|
|
588
|
-
|
|
772
|
+
success(`Deployed ${team.name} ( ${team['$id']} )`);
|
|
773
|
+
} catch (e) {
|
|
774
|
+
if (e.code == 404) {
|
|
775
|
+
log(`Team ${team.name} does not exist in the project. Creating ... `);
|
|
776
|
+
|
|
777
|
+
response = await teamsCreate({
|
|
778
|
+
teamId: team['$id'],
|
|
779
|
+
name: team.name,
|
|
780
|
+
parseOutput: false
|
|
781
|
+
})
|
|
782
|
+
|
|
783
|
+
success(`Deployed ${team.name} ( ${team['$id']} )`);
|
|
589
784
|
} else {
|
|
590
785
|
throw e;
|
|
591
786
|
}
|
|
@@ -608,6 +803,20 @@ deploy
|
|
|
608
803
|
.option(`--yes`, `Flag to confirm all warnings`)
|
|
609
804
|
.action(actionRunner(deployCollection));
|
|
610
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
|
+
|
|
813
|
+
deploy
|
|
814
|
+
.command("team")
|
|
815
|
+
.description("Deploy teams in the current project.")
|
|
816
|
+
.option(`--all`, `Flag to deploy all teams`)
|
|
817
|
+
.option(`--yes`, `Flag to confirm all warnings`)
|
|
818
|
+
.action(actionRunner(deployTeam));
|
|
819
|
+
|
|
611
820
|
module.exports = {
|
|
612
821
|
deploy
|
|
613
822
|
}
|