appwrite-cli 0.15.0 → 0.17.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/.github/workflows/npm-publish.yml +0 -1
- package/README.md +4 -4
- package/docs/examples/account/update-status.md +1 -0
- package/docs/examples/teams/list-logs.md +4 -0
- package/docs/examples/users/get-memberships.md +2 -0
- package/install.ps1 +9 -5
- package/install.sh +1 -1
- package/lib/client.js +6 -7
- package/lib/commands/account.js +32 -29
- package/lib/commands/avatars.js +13 -10
- package/lib/commands/database.js +15 -12
- package/lib/commands/deploy.js +5 -4
- package/lib/commands/functions.js +66 -41
- package/lib/commands/generic.js +11 -4
- package/lib/commands/health.js +4 -24
- package/lib/commands/init.js +1 -0
- package/lib/commands/locale.js +4 -1
- package/lib/commands/projects.js +8 -5
- package/lib/commands/storage.js +50 -36
- package/lib/commands/teams.js +44 -4
- package/lib/commands/users.js +32 -4
- package/lib/config.js +6 -4
- package/lib/questions.js +44 -3
- package/lib/sdks.js +17 -1
- package/lib/utils.js +19 -0
- package/package.json +8 -6
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
+
const pathLib = require('path');
|
|
2
3
|
const tar = require("tar");
|
|
4
|
+
const ignore = require("ignore");
|
|
3
5
|
const { promisify } = require('util');
|
|
4
6
|
const libClient = require('../client.js');
|
|
7
|
+
const { getAllFiles } = require('../utils.js');
|
|
5
8
|
const { Command } = require('commander');
|
|
6
9
|
const { sdkForProject, sdkForConsole } = require('../sdks')
|
|
7
10
|
const { parse, actionRunner, parseInteger, parseBool, commandDescriptions, success, log } = require('../parser')
|
|
@@ -84,7 +87,7 @@ const functionsCreate = async ({ functionId, name, execute, runtime, vars, event
|
|
|
84
87
|
}
|
|
85
88
|
|
|
86
89
|
if (typeof vars !== 'undefined') {
|
|
87
|
-
payload['vars'] = vars;
|
|
90
|
+
payload['vars'] = JSON.parse(vars);
|
|
88
91
|
}
|
|
89
92
|
|
|
90
93
|
if (typeof events !== 'undefined') {
|
|
@@ -169,7 +172,7 @@ const functionsUpdate = async ({ functionId, name, execute, vars, events, schedu
|
|
|
169
172
|
}
|
|
170
173
|
|
|
171
174
|
if (typeof vars !== 'undefined') {
|
|
172
|
-
payload['vars'] = vars;
|
|
175
|
+
payload['vars'] = JSON.parse(vars);
|
|
173
176
|
}
|
|
174
177
|
|
|
175
178
|
if (typeof events !== 'undefined') {
|
|
@@ -277,16 +280,31 @@ const functionsCreateDeployment = async ({ functionId, entrypoint, code, activat
|
|
|
277
280
|
if (!fs.lstatSync(folderPath).isDirectory())
|
|
278
281
|
throw new Error('The path is not a directory.');
|
|
279
282
|
|
|
283
|
+
const ignorer = ignore();
|
|
284
|
+
|
|
285
|
+
const func = localConfig.getFunction(functionId);
|
|
286
|
+
|
|
287
|
+
if(func.ignore) {
|
|
288
|
+
ignorer.add(func.ignore);
|
|
289
|
+
log('Ignoring files using configuration from appwrite.json');
|
|
290
|
+
} else if(fs.existsSync(pathLib.join(code, '.gitignore'))) {
|
|
291
|
+
ignorer.add(fs.readFileSync(pathLib.join(code, '.gitignore')).toString());
|
|
292
|
+
log('Ignoring files in .gitignore');
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const files = getAllFiles(code).map((file) => pathLib.relative(code, file)).filter((file) => !ignorer.ignores(file));
|
|
296
|
+
|
|
280
297
|
await tar
|
|
281
298
|
.create({
|
|
282
299
|
gzip: true,
|
|
283
300
|
sync: true,
|
|
284
301
|
cwd: folderPath,
|
|
285
302
|
file: 'code.tar.gz'
|
|
286
|
-
},
|
|
303
|
+
}, files);
|
|
287
304
|
let archivePath = fs.realpathSync('code.tar.gz')
|
|
288
305
|
if (typeof archivePath !== 'undefined') {
|
|
289
306
|
payload['code'] = archivePath;
|
|
307
|
+
code = archivePath;
|
|
290
308
|
}
|
|
291
309
|
|
|
292
310
|
if (typeof activate !== 'undefined') {
|
|
@@ -301,46 +319,53 @@ const functionsCreateDeployment = async ({ functionId, entrypoint, code, activat
|
|
|
301
319
|
|
|
302
320
|
response = await client.call('post', path, {
|
|
303
321
|
'content-type': 'multipart/form-data',
|
|
304
|
-
}, payload)
|
|
322
|
+
}, payload).catch(err => {
|
|
323
|
+
fs.unlinkSync(archivePath);
|
|
324
|
+
throw err
|
|
325
|
+
});
|
|
305
326
|
} else {
|
|
306
327
|
const streamFilePath = payload['code'];
|
|
307
328
|
let id = undefined;
|
|
308
329
|
|
|
330
|
+
let counter = 0;
|
|
309
331
|
const totalCounters = Math.ceil(size / libClient.CHUNK_SIZE);
|
|
310
332
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
333
|
+
const headers = {
|
|
334
|
+
'content-type': 'multipart/form-data',
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
for (counter; counter < totalCounters; counter++) {
|
|
339
|
+
const start = (counter * libClient.CHUNK_SIZE);
|
|
340
|
+
const end = Math.min((((counter * libClient.CHUNK_SIZE) + libClient.CHUNK_SIZE) - 1), size);
|
|
341
|
+
|
|
342
|
+
headers['content-range'] = 'bytes ' + start + '-' + end + '/' + size;
|
|
343
|
+
|
|
344
|
+
if (id) {
|
|
345
|
+
headers['x-appwrite-id'] = id;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const stream = fs.createReadStream(streamFilePath, {
|
|
349
|
+
start,
|
|
350
|
+
end
|
|
351
|
+
});
|
|
352
|
+
payload['code'] = stream;
|
|
353
|
+
|
|
354
|
+
response = await client.call('post', path, headers, payload);
|
|
355
|
+
|
|
356
|
+
if (!id) {
|
|
357
|
+
id = response['$id'];
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (onProgress !== null) {
|
|
361
|
+
onProgress({
|
|
362
|
+
$id: response['$id'],
|
|
363
|
+
progress: Math.min((counter+1) * libClient.CHUNK_SIZE, size) / size * 100,
|
|
364
|
+
sizeUploaded: end+1,
|
|
365
|
+
chunksTotal: response['chunksTotal'],
|
|
366
|
+
chunksUploaded: response['chunksUploaded']
|
|
326
367
|
});
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
response = await client.call('post', path, headers, payload);
|
|
330
|
-
|
|
331
|
-
if (!id) {
|
|
332
|
-
id = response['$id'];
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
if (onProgress !== null) {
|
|
336
|
-
onProgress({
|
|
337
|
-
$id: response['$id'],
|
|
338
|
-
progress: Math.min((counter+1) * libClient.CHUNK_SIZE, size) / size * 100,
|
|
339
|
-
sizeUploaded: end+1,
|
|
340
|
-
chunksTotal: response['chunksTotal'],
|
|
341
|
-
chunksUploaded: response['chunksUploaded']
|
|
342
|
-
});
|
|
343
|
-
}
|
|
368
|
+
}
|
|
344
369
|
}
|
|
345
370
|
}
|
|
346
371
|
|
|
@@ -560,10 +585,10 @@ functions
|
|
|
560
585
|
.description(`Create a new function. You can pass a list of [permissions](/docs/permissions) to allow different project users or team with access to execute the function using the client API.`)
|
|
561
586
|
.requiredOption(`--functionId <functionId>`, `Function ID. Choose your own unique ID or pass the string "unique()" to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.`)
|
|
562
587
|
.requiredOption(`--name <name>`, `Function name. Max length: 128 chars.`)
|
|
563
|
-
.requiredOption(`--execute <execute...>`, `An array of strings with execution permissions. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.`)
|
|
588
|
+
.requiredOption(`--execute <execute...>`, `An array of strings with execution permissions. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions. Maximum of 100 scopes are allowed, each 64 characters long.`)
|
|
564
589
|
.requiredOption(`--runtime <runtime>`, `Execution runtime.`)
|
|
565
590
|
.option(`--vars <vars>`, `Key-value JSON object that will be passed to the function as environment variables.`)
|
|
566
|
-
.option(`--events <events...>`, `Events list.`)
|
|
591
|
+
.option(`--events <events...>`, `Events list. Maximum of 100 events are allowed.`)
|
|
567
592
|
.option(`--schedule <schedule>`, `Schedule CRON syntax.`)
|
|
568
593
|
.option(`--timeout <timeout>`, `Function maximum execution time in seconds.`, parseInteger)
|
|
569
594
|
.action(actionRunner(functionsCreate))
|
|
@@ -584,9 +609,9 @@ functions
|
|
|
584
609
|
.description(`Update function by its unique ID.`)
|
|
585
610
|
.requiredOption(`--functionId <functionId>`, `Function ID.`)
|
|
586
611
|
.requiredOption(`--name <name>`, `Function name. Max length: 128 chars.`)
|
|
587
|
-
.requiredOption(`--execute <execute...>`, `An array of strings with execution permissions. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions.`)
|
|
612
|
+
.requiredOption(`--execute <execute...>`, `An array of strings with execution permissions. By default no user is granted with any execute permissions. [learn more about permissions](https://appwrite.io/docs/permissions) and get a full list of available permissions. Maximum of 100 scopes are allowed, each 64 characters long.`)
|
|
588
613
|
.option(`--vars <vars>`, `Key-value JSON object that will be passed to the function as environment variables.`)
|
|
589
|
-
.option(`--events <events...>`, `Events list.`)
|
|
614
|
+
.option(`--events <events...>`, `Events list. Maximum of 100 events are allowed.`)
|
|
590
615
|
.option(`--schedule <schedule>`, `Schedule CRON syntax.`)
|
|
591
616
|
.option(`--timeout <timeout>`, `Maximum execution time in seconds.`, parseInteger)
|
|
592
617
|
.action(actionRunner(functionsUpdate))
|
|
@@ -699,4 +724,4 @@ module.exports = {
|
|
|
699
724
|
functionsCreateExecution,
|
|
700
725
|
functionsGetExecution,
|
|
701
726
|
functionsGetUsage
|
|
702
|
-
};
|
|
727
|
+
};
|
package/lib/commands/generic.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const inquirer = require("inquirer");
|
|
2
2
|
const { Command } = require("commander");
|
|
3
|
+
const Client = require("../client");
|
|
3
4
|
const { sdkForConsole } = require("../sdks");
|
|
4
5
|
const { globalConfig, localConfig } = require("../config");
|
|
5
6
|
const { actionRunner, success, parseBool, commandDescriptions, log, parse } = require("../parser");
|
|
@@ -65,13 +66,19 @@ const client = new Command("client")
|
|
|
65
66
|
if (endpoint !== undefined) {
|
|
66
67
|
try {
|
|
67
68
|
let url = new URL(endpoint);
|
|
68
|
-
if (url.protocol
|
|
69
|
-
globalConfig.setEndpoint(endpoint);
|
|
70
|
-
} else {
|
|
69
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
71
70
|
throw new Error();
|
|
72
71
|
}
|
|
72
|
+
|
|
73
|
+
let client = new Client().setEndpoint(endpoint);
|
|
74
|
+
let response = await client.call('GET', '/health/version');
|
|
75
|
+
if(!response.version) {
|
|
76
|
+
throw new Error();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
globalConfig.setEndpoint(endpoint);
|
|
73
80
|
} catch (_) {
|
|
74
|
-
throw new Error("Invalid endpoint");
|
|
81
|
+
throw new Error("Invalid endpoint or your Appwrite server is not running as expected.");
|
|
75
82
|
}
|
|
76
83
|
}
|
|
77
84
|
|
package/lib/commands/health.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
+
const pathLib = require('path');
|
|
2
3
|
const tar = require("tar");
|
|
4
|
+
const ignore = require("ignore");
|
|
3
5
|
const { promisify } = require('util');
|
|
4
6
|
const libClient = require('../client.js');
|
|
7
|
+
const { getAllFiles } = require('../utils.js');
|
|
5
8
|
const { Command } = require('commander');
|
|
6
9
|
const { sdkForProject, sdkForConsole } = require('../sdks')
|
|
7
10
|
const { parse, actionRunner, parseInteger, parseBool, commandDescriptions, success, log } = require('../parser')
|
|
@@ -128,23 +131,6 @@ const healthGetQueueLogs = async ({ parseOutput = true, sdk = undefined}) => {
|
|
|
128
131
|
return response;
|
|
129
132
|
}
|
|
130
133
|
|
|
131
|
-
const healthGetQueueUsage = async ({ parseOutput = true, sdk = undefined}) => {
|
|
132
|
-
|
|
133
|
-
let client = !sdk ? await sdkForProject() : sdk;
|
|
134
|
-
let path = '/health/queue/usage';
|
|
135
|
-
let payload = {};
|
|
136
|
-
let response = undefined;
|
|
137
|
-
response = await client.call('get', path, {
|
|
138
|
-
'content-type': 'application/json',
|
|
139
|
-
}, payload);
|
|
140
|
-
|
|
141
|
-
if (parseOutput) {
|
|
142
|
-
parse(response)
|
|
143
|
-
success()
|
|
144
|
-
}
|
|
145
|
-
return response;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
134
|
const healthGetQueueWebhooks = async ({ parseOutput = true, sdk = undefined}) => {
|
|
149
135
|
|
|
150
136
|
let client = !sdk ? await sdkForProject() : sdk;
|
|
@@ -232,11 +218,6 @@ health
|
|
|
232
218
|
.description(`Get the number of logs that are waiting to be processed in the Appwrite internal queue server.`)
|
|
233
219
|
.action(actionRunner(healthGetQueueLogs))
|
|
234
220
|
|
|
235
|
-
health
|
|
236
|
-
.command(`getQueueUsage`)
|
|
237
|
-
.description(`Get the number of usage stats that are waiting to be processed in the Appwrite internal queue server.`)
|
|
238
|
-
.action(actionRunner(healthGetQueueUsage))
|
|
239
|
-
|
|
240
221
|
health
|
|
241
222
|
.command(`getQueueWebhooks`)
|
|
242
223
|
.description(`Get the number of webhooks that are waiting to be processed in the Appwrite internal queue server.`)
|
|
@@ -262,8 +243,7 @@ module.exports = {
|
|
|
262
243
|
healthGetQueueCertificates,
|
|
263
244
|
healthGetQueueFunctions,
|
|
264
245
|
healthGetQueueLogs,
|
|
265
|
-
healthGetQueueUsage,
|
|
266
246
|
healthGetQueueWebhooks,
|
|
267
247
|
healthGetStorageLocal,
|
|
268
248
|
healthGetTime
|
|
269
|
-
};
|
|
249
|
+
};
|
package/lib/commands/init.js
CHANGED
|
@@ -99,6 +99,7 @@ const initFunction = async () => {
|
|
|
99
99
|
runtime: response.runtime,
|
|
100
100
|
path: `functions/${answers.name}`,
|
|
101
101
|
entrypoint: answers.runtime.entrypoint || '',
|
|
102
|
+
ignore: answers.runtime.ignore || null,
|
|
102
103
|
execute: response.execute,
|
|
103
104
|
events: response.events,
|
|
104
105
|
schedule: response.schedule,
|
package/lib/commands/locale.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
+
const pathLib = require('path');
|
|
2
3
|
const tar = require("tar");
|
|
4
|
+
const ignore = require("ignore");
|
|
3
5
|
const { promisify } = require('util');
|
|
4
6
|
const libClient = require('../client.js');
|
|
7
|
+
const { getAllFiles } = require('../utils.js');
|
|
5
8
|
const { Command } = require('commander');
|
|
6
9
|
const { sdkForProject, sdkForConsole } = require('../sdks')
|
|
7
10
|
const { parse, actionRunner, parseInteger, parseBool, commandDescriptions, success, log } = require('../parser')
|
|
@@ -174,4 +177,4 @@ module.exports = {
|
|
|
174
177
|
localeGetCountriesPhones,
|
|
175
178
|
localeGetCurrencies,
|
|
176
179
|
localeGetLanguages
|
|
177
|
-
};
|
|
180
|
+
};
|
package/lib/commands/projects.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
+
const pathLib = require('path');
|
|
2
3
|
const tar = require("tar");
|
|
4
|
+
const ignore = require("ignore");
|
|
3
5
|
const { promisify } = require('util');
|
|
4
6
|
const libClient = require('../client.js');
|
|
7
|
+
const { getAllFiles } = require('../utils.js');
|
|
5
8
|
const { Command } = require('commander');
|
|
6
9
|
const { sdkForProject, sdkForConsole } = require('../sdks')
|
|
7
10
|
const { parse, actionRunner, parseInteger, parseBool, commandDescriptions, success, log } = require('../parser')
|
|
@@ -1018,7 +1021,7 @@ projects
|
|
|
1018
1021
|
.description(``)
|
|
1019
1022
|
.requiredOption(`--projectId <projectId>`, `Project unique ID.`)
|
|
1020
1023
|
.requiredOption(`--name <name>`, `Key name. Max length: 128 chars.`)
|
|
1021
|
-
.requiredOption(`--scopes <scopes...>`, `Key scopes list.`)
|
|
1024
|
+
.requiredOption(`--scopes <scopes...>`, `Key scopes list. Maximum of 100 scopes are allowed.`)
|
|
1022
1025
|
.action(actionRunner(projectsCreateKey))
|
|
1023
1026
|
|
|
1024
1027
|
projects
|
|
@@ -1034,7 +1037,7 @@ projects
|
|
|
1034
1037
|
.requiredOption(`--projectId <projectId>`, `Project unique ID.`)
|
|
1035
1038
|
.requiredOption(`--keyId <keyId>`, `Key unique ID.`)
|
|
1036
1039
|
.requiredOption(`--name <name>`, `Key name. Max length: 128 chars.`)
|
|
1037
|
-
.requiredOption(`--scopes <scopes...>`, `Key scopes list
|
|
1040
|
+
.requiredOption(`--scopes <scopes...>`, `Key scopes list. Maximum of 100 events are allowed.`)
|
|
1038
1041
|
.action(actionRunner(projectsUpdateKey))
|
|
1039
1042
|
|
|
1040
1043
|
projects
|
|
@@ -1121,7 +1124,7 @@ projects
|
|
|
1121
1124
|
.description(``)
|
|
1122
1125
|
.requiredOption(`--projectId <projectId>`, `Project unique ID.`)
|
|
1123
1126
|
.requiredOption(`--name <name>`, `Webhook name. Max length: 128 chars.`)
|
|
1124
|
-
.requiredOption(`--events <events...>`, `Events list.`)
|
|
1127
|
+
.requiredOption(`--events <events...>`, `Events list. Maximum of 100 events are allowed.`)
|
|
1125
1128
|
.requiredOption(`--url <url>`, `Webhook URL.`)
|
|
1126
1129
|
.requiredOption(`--security <security>`, `Certificate verification, false for disabled or true for enabled.`, parseBool)
|
|
1127
1130
|
.option(`--httpUser <httpUser>`, `Webhook HTTP user. Max length: 256 chars.`)
|
|
@@ -1141,7 +1144,7 @@ projects
|
|
|
1141
1144
|
.requiredOption(`--projectId <projectId>`, `Project unique ID.`)
|
|
1142
1145
|
.requiredOption(`--webhookId <webhookId>`, `Webhook unique ID.`)
|
|
1143
1146
|
.requiredOption(`--name <name>`, `Webhook name. Max length: 128 chars.`)
|
|
1144
|
-
.requiredOption(`--events <events...>`, `Events list.`)
|
|
1147
|
+
.requiredOption(`--events <events...>`, `Events list. Maximum of 100 events are allowed.`)
|
|
1145
1148
|
.requiredOption(`--url <url>`, `Webhook URL.`)
|
|
1146
1149
|
.requiredOption(`--security <security>`, `Certificate verification, false for disabled or true for enabled.`, parseBool)
|
|
1147
1150
|
.option(`--httpUser <httpUser>`, `Webhook HTTP user. Max length: 256 chars.`)
|
|
@@ -1188,4 +1191,4 @@ module.exports = {
|
|
|
1188
1191
|
projectsGetWebhook,
|
|
1189
1192
|
projectsUpdateWebhook,
|
|
1190
1193
|
projectsDeleteWebhook
|
|
1191
|
-
};
|
|
1194
|
+
};
|
package/lib/commands/storage.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
+
const pathLib = require('path');
|
|
2
3
|
const tar = require("tar");
|
|
4
|
+
const ignore = require("ignore");
|
|
3
5
|
const { promisify } = require('util');
|
|
4
6
|
const libClient = require('../client.js');
|
|
7
|
+
const { getAllFiles } = require('../utils.js');
|
|
5
8
|
const { Command } = require('commander');
|
|
6
9
|
const { sdkForProject, sdkForConsole } = require('../sdks')
|
|
7
10
|
const { parse, actionRunner, parseInteger, parseBool, commandDescriptions, success, log } = require('../parser')
|
|
@@ -303,46 +306,57 @@ const storageCreateFile = async ({ bucketId, fileId, file, read, write, parseOut
|
|
|
303
306
|
|
|
304
307
|
response = await client.call('post', path, {
|
|
305
308
|
'content-type': 'multipart/form-data',
|
|
306
|
-
}, payload)
|
|
309
|
+
}, payload)
|
|
307
310
|
} else {
|
|
308
311
|
const streamFilePath = payload['file'];
|
|
309
312
|
let id = undefined;
|
|
310
313
|
|
|
314
|
+
let counter = 0;
|
|
311
315
|
const totalCounters = Math.ceil(size / libClient.CHUNK_SIZE);
|
|
312
316
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
317
|
+
const headers = {
|
|
318
|
+
'content-type': 'multipart/form-data',
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
if(fileId != 'unique()') {
|
|
322
|
+
try {
|
|
323
|
+
response = await client.call('get', path + '/' + fileId, headers);
|
|
324
|
+
counter = response.chunksUploaded;
|
|
325
|
+
} catch(e) {
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
for (counter; counter < totalCounters; counter++) {
|
|
330
|
+
const start = (counter * libClient.CHUNK_SIZE);
|
|
331
|
+
const end = Math.min((((counter * libClient.CHUNK_SIZE) + libClient.CHUNK_SIZE) - 1), size);
|
|
332
|
+
|
|
333
|
+
headers['content-range'] = 'bytes ' + start + '-' + end + '/' + size;
|
|
334
|
+
|
|
335
|
+
if (id) {
|
|
336
|
+
headers['x-appwrite-id'] = id;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const stream = fs.createReadStream(streamFilePath, {
|
|
340
|
+
start,
|
|
341
|
+
end
|
|
342
|
+
});
|
|
343
|
+
payload['file'] = stream;
|
|
344
|
+
|
|
345
|
+
response = await client.call('post', path, headers, payload);
|
|
346
|
+
|
|
347
|
+
if (!id) {
|
|
348
|
+
id = response['$id'];
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (onProgress !== null) {
|
|
352
|
+
onProgress({
|
|
353
|
+
$id: response['$id'],
|
|
354
|
+
progress: Math.min((counter+1) * libClient.CHUNK_SIZE, size) / size * 100,
|
|
355
|
+
sizeUploaded: end+1,
|
|
356
|
+
chunksTotal: response['chunksTotal'],
|
|
357
|
+
chunksUploaded: response['chunksUploaded']
|
|
328
358
|
});
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
response = await client.call('post', path, headers, payload);
|
|
332
|
-
|
|
333
|
-
if (!id) {
|
|
334
|
-
id = response['$id'];
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
if (onProgress !== null) {
|
|
338
|
-
onProgress({
|
|
339
|
-
$id: response['$id'],
|
|
340
|
-
progress: Math.min((counter+1) * libClient.CHUNK_SIZE, size) / size * 100,
|
|
341
|
-
sizeUploaded: end+1,
|
|
342
|
-
chunksTotal: response['chunksTotal'],
|
|
343
|
-
chunksUploaded: response['chunksUploaded']
|
|
344
|
-
});
|
|
345
|
-
}
|
|
359
|
+
}
|
|
346
360
|
}
|
|
347
361
|
}
|
|
348
362
|
|
|
@@ -609,7 +623,7 @@ storage
|
|
|
609
623
|
.option(`--write <write...>`, `An array of strings with write permissions. By default no user is granted with any write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.`)
|
|
610
624
|
.option(`--enabled <enabled>`, `Is bucket enabled?`, parseBool)
|
|
611
625
|
.option(`--maximumFileSize <maximumFileSize>`, `Maximum file size allowed in bytes. Maximum allowed value is 30MB. For self-hosted setups you can change the max limit by changing the '_APP_STORAGE_LIMIT' environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)`, parseInteger)
|
|
612
|
-
.option(`--allowedFileExtensions <allowedFileExtensions...>`, `Allowed file extensions
|
|
626
|
+
.option(`--allowedFileExtensions <allowedFileExtensions...>`, `Allowed file extensions. Maximum of 100 extensions are allowed, each 64 characters long.`)
|
|
613
627
|
.option(`--encryption <encryption>`, `Is encryption enabled? For file size above 20MB encryption is skipped even if it's enabled`, parseBool)
|
|
614
628
|
.option(`--antivirus <antivirus>`, `Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled`, parseBool)
|
|
615
629
|
.action(actionRunner(storageCreateBucket))
|
|
@@ -630,7 +644,7 @@ storage
|
|
|
630
644
|
.option(`--write <write...>`, `An array of strings with write permissions. By default inherits the existing write permissions. [learn more about permissions](/docs/permissions) and get a full list of available permissions.`)
|
|
631
645
|
.option(`--enabled <enabled>`, `Is bucket enabled?`, parseBool)
|
|
632
646
|
.option(`--maximumFileSize <maximumFileSize>`, `Maximum file size allowed in bytes. Maximum allowed value is 30MB. For self hosted version you can change the limit by changing _APP_STORAGE_LIMIT environment variable. [Learn more about storage environment variables](docs/environment-variables#storage)`, parseInteger)
|
|
633
|
-
.option(`--allowedFileExtensions <allowedFileExtensions...>`, `Allowed file extensions
|
|
647
|
+
.option(`--allowedFileExtensions <allowedFileExtensions...>`, `Allowed file extensions. Maximum of 100 extensions are allowed, each 64 characters long.`)
|
|
634
648
|
.option(`--encryption <encryption>`, `Is encryption enabled? For file size above 20MB encryption is skipped even if it's enabled`, parseBool)
|
|
635
649
|
.option(`--antivirus <antivirus>`, `Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled`, parseBool)
|
|
636
650
|
.action(actionRunner(storageUpdateBucket))
|
|
@@ -752,4 +766,4 @@ module.exports = {
|
|
|
752
766
|
storageGetFileView,
|
|
753
767
|
storageGetUsage,
|
|
754
768
|
storageGetBucketUsage
|
|
755
|
-
};
|
|
769
|
+
};
|
package/lib/commands/teams.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
+
const pathLib = require('path');
|
|
2
3
|
const tar = require("tar");
|
|
4
|
+
const ignore = require("ignore");
|
|
3
5
|
const { promisify } = require('util');
|
|
4
6
|
const libClient = require('../client.js');
|
|
7
|
+
const { getAllFiles } = require('../utils.js');
|
|
5
8
|
const { Command } = require('commander');
|
|
6
9
|
const { sdkForProject, sdkForConsole } = require('../sdks')
|
|
7
10
|
const { parse, actionRunner, parseInteger, parseBool, commandDescriptions, success, log } = require('../parser')
|
|
@@ -147,6 +150,34 @@ const teamsDelete = async ({ teamId, parseOutput = true, sdk = undefined}) => {
|
|
|
147
150
|
return response;
|
|
148
151
|
}
|
|
149
152
|
|
|
153
|
+
const teamsListLogs = async ({ teamId, limit, offset, parseOutput = true, sdk = undefined}) => {
|
|
154
|
+
/* @param {string} teamId */
|
|
155
|
+
/* @param {number} limit */
|
|
156
|
+
/* @param {number} offset */
|
|
157
|
+
|
|
158
|
+
let client = !sdk ? await sdkForProject() : sdk;
|
|
159
|
+
let path = '/teams/{teamId}/logs'.replace('{teamId}', teamId);
|
|
160
|
+
let payload = {};
|
|
161
|
+
|
|
162
|
+
/** Query Params */
|
|
163
|
+
if (typeof limit !== 'undefined') {
|
|
164
|
+
payload['limit'] = limit;
|
|
165
|
+
}
|
|
166
|
+
if (typeof offset !== 'undefined') {
|
|
167
|
+
payload['offset'] = offset;
|
|
168
|
+
}
|
|
169
|
+
let response = undefined;
|
|
170
|
+
response = await client.call('get', path, {
|
|
171
|
+
'content-type': 'application/json',
|
|
172
|
+
}, payload);
|
|
173
|
+
|
|
174
|
+
if (parseOutput) {
|
|
175
|
+
parse(response)
|
|
176
|
+
success()
|
|
177
|
+
}
|
|
178
|
+
return response;
|
|
179
|
+
}
|
|
180
|
+
|
|
150
181
|
const teamsGetMemberships = async ({ teamId, search, limit, offset, cursor, cursorDirection, orderType, parseOutput = true, sdk = undefined}) => {
|
|
151
182
|
/* @param {string} teamId */
|
|
152
183
|
/* @param {string} search */
|
|
@@ -343,7 +374,7 @@ teams
|
|
|
343
374
|
.description(`Create a new team. The user who creates the team will automatically be assigned as the owner of the team. Only the users with the owner role can invite new members, add new owners and delete or update the team.`)
|
|
344
375
|
.requiredOption(`--teamId <teamId>`, `Team ID. Choose your own unique ID or pass the string "unique()" to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.`)
|
|
345
376
|
.requiredOption(`--name <name>`, `Team name. Max length: 128 chars.`)
|
|
346
|
-
.option(`--roles <roles...>`, `Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](/docs/permissions).
|
|
377
|
+
.option(`--roles <roles...>`, `Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Maximum of 100 roles are allowed, each 32 characters long.`)
|
|
347
378
|
.action(actionRunner(teamsCreate))
|
|
348
379
|
|
|
349
380
|
teams
|
|
@@ -365,6 +396,14 @@ teams
|
|
|
365
396
|
.requiredOption(`--teamId <teamId>`, `Team ID.`)
|
|
366
397
|
.action(actionRunner(teamsDelete))
|
|
367
398
|
|
|
399
|
+
teams
|
|
400
|
+
.command(`listLogs`)
|
|
401
|
+
.description(`Get the team activity logs list by its unique ID.`)
|
|
402
|
+
.requiredOption(`--teamId <teamId>`, `Team ID.`)
|
|
403
|
+
.option(`--limit <limit>`, `Maximum number of logs to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.`, parseInteger)
|
|
404
|
+
.option(`--offset <offset>`, `Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)`, parseInteger)
|
|
405
|
+
.action(actionRunner(teamsListLogs))
|
|
406
|
+
|
|
368
407
|
teams
|
|
369
408
|
.command(`getMemberships`)
|
|
370
409
|
.description(`Use this endpoint to list a team's members using the team's ID. All team members have read access to this endpoint.`)
|
|
@@ -382,7 +421,7 @@ teams
|
|
|
382
421
|
.description(`Invite a new member to join your team. If initiated from the client SDK, an email with a link to join the team will be sent to the member's email address and an account will be created for them should they not be signed up already. If initiated from server-side SDKs, the new member will automatically be added to the team. Use the 'url' parameter to redirect the user from the invitation email back to your app. When the user is redirected, use the [Update Team Membership Status](/docs/client/teams#teamsUpdateMembershipStatus) endpoint to allow the user to accept the invitation to the team. Please note that to avoid a [Redirect Attack](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) the only valid redirect URL's are the once from domains you have set when adding your platforms in the console interface.`)
|
|
383
422
|
.requiredOption(`--teamId <teamId>`, `Team ID.`)
|
|
384
423
|
.requiredOption(`--email <email>`, `Email of the new team member.`)
|
|
385
|
-
.requiredOption(`--roles <roles...>`, `Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](/docs/permissions).
|
|
424
|
+
.requiredOption(`--roles <roles...>`, `Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](/docs/permissions). Maximum of 100 roles are allowed, each 32 characters long.`)
|
|
386
425
|
.requiredOption(`--url <url>`, `URL to redirect the user back to your app from the invitation email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.`)
|
|
387
426
|
.option(`--name <name>`, `Name of the new team member. Max length: 128 chars.`)
|
|
388
427
|
.action(actionRunner(teamsCreateMembership))
|
|
@@ -399,7 +438,7 @@ teams
|
|
|
399
438
|
.description(`Modify the roles of a team member. Only team members with the owner role have access to this endpoint. Learn more about [roles and permissions](/docs/permissions).`)
|
|
400
439
|
.requiredOption(`--teamId <teamId>`, `Team ID.`)
|
|
401
440
|
.requiredOption(`--membershipId <membershipId>`, `Membership ID.`)
|
|
402
|
-
.requiredOption(`--roles <roles...>`, `An array of strings. Use this param to set the user's roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions).
|
|
441
|
+
.requiredOption(`--roles <roles...>`, `An array of strings. Use this param to set the user's roles in the team. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of 100 roles are allowed, each 32 characters long.`)
|
|
403
442
|
.action(actionRunner(teamsUpdateMembershipRoles))
|
|
404
443
|
|
|
405
444
|
teams
|
|
@@ -426,10 +465,11 @@ module.exports = {
|
|
|
426
465
|
teamsGet,
|
|
427
466
|
teamsUpdate,
|
|
428
467
|
teamsDelete,
|
|
468
|
+
teamsListLogs,
|
|
429
469
|
teamsGetMemberships,
|
|
430
470
|
teamsCreateMembership,
|
|
431
471
|
teamsGetMembership,
|
|
432
472
|
teamsUpdateMembershipRoles,
|
|
433
473
|
teamsDeleteMembership,
|
|
434
474
|
teamsUpdateMembershipStatus
|
|
435
|
-
};
|
|
475
|
+
};
|
package/lib/commands/users.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
+
const pathLib = require('path');
|
|
2
3
|
const tar = require("tar");
|
|
4
|
+
const ignore = require("ignore");
|
|
3
5
|
const { promisify } = require('util');
|
|
4
6
|
const libClient = require('../client.js');
|
|
7
|
+
const { getAllFiles } = require('../utils.js');
|
|
5
8
|
const { Command } = require('commander');
|
|
6
9
|
const { sdkForProject, sdkForConsole } = require('../sdks')
|
|
7
10
|
const { parse, actionRunner, parseInteger, parseBool, commandDescriptions, success, log } = require('../parser')
|
|
@@ -207,6 +210,24 @@ const usersGetLogs = async ({ userId, limit, offset, parseOutput = true, sdk = u
|
|
|
207
210
|
return response;
|
|
208
211
|
}
|
|
209
212
|
|
|
213
|
+
const usersGetMemberships = async ({ userId, parseOutput = true, sdk = undefined}) => {
|
|
214
|
+
/* @param {string} userId */
|
|
215
|
+
|
|
216
|
+
let client = !sdk ? await sdkForProject() : sdk;
|
|
217
|
+
let path = '/users/{userId}/memberships'.replace('{userId}', userId);
|
|
218
|
+
let payload = {};
|
|
219
|
+
let response = undefined;
|
|
220
|
+
response = await client.call('get', path, {
|
|
221
|
+
'content-type': 'application/json',
|
|
222
|
+
}, payload);
|
|
223
|
+
|
|
224
|
+
if (parseOutput) {
|
|
225
|
+
parse(response)
|
|
226
|
+
success()
|
|
227
|
+
}
|
|
228
|
+
return response;
|
|
229
|
+
}
|
|
230
|
+
|
|
210
231
|
const usersUpdateName = async ({ userId, name, parseOutput = true, sdk = undefined}) => {
|
|
211
232
|
/* @param {string} userId */
|
|
212
233
|
/* @param {string} name */
|
|
@@ -285,7 +306,7 @@ const usersUpdatePrefs = async ({ userId, prefs, parseOutput = true, sdk = undef
|
|
|
285
306
|
|
|
286
307
|
/** Body Params */
|
|
287
308
|
if (typeof prefs !== 'undefined') {
|
|
288
|
-
payload['prefs'] = prefs;
|
|
309
|
+
payload['prefs'] = JSON.parse(prefs);
|
|
289
310
|
}
|
|
290
311
|
|
|
291
312
|
let response = undefined;
|
|
@@ -441,7 +462,7 @@ users
|
|
|
441
462
|
|
|
442
463
|
users
|
|
443
464
|
.command(`delete`)
|
|
444
|
-
.description(`Delete a user by its unique ID.`)
|
|
465
|
+
.description(`Delete a user by its unique ID, thereby releasing it's ID. Since ID is released and can be reused, all user-related resources like documents or storage files should be deleted before user deletion. If you want to keep ID reserved, use the [updateStatus](/docs/server/users#usersUpdateStatus) endpoint instead.`)
|
|
445
466
|
.requiredOption(`--userId <userId>`, `User ID.`)
|
|
446
467
|
.action(actionRunner(usersDelete))
|
|
447
468
|
|
|
@@ -460,6 +481,12 @@ users
|
|
|
460
481
|
.option(`--offset <offset>`, `Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)`, parseInteger)
|
|
461
482
|
.action(actionRunner(usersGetLogs))
|
|
462
483
|
|
|
484
|
+
users
|
|
485
|
+
.command(`getMemberships`)
|
|
486
|
+
.description(`Get the user membership list by its unique ID.`)
|
|
487
|
+
.requiredOption(`--userId <userId>`, `User ID.`)
|
|
488
|
+
.action(actionRunner(usersGetMemberships))
|
|
489
|
+
|
|
463
490
|
users
|
|
464
491
|
.command(`updateName`)
|
|
465
492
|
.description(`Update the user name by its unique ID.`)
|
|
@@ -508,7 +535,7 @@ users
|
|
|
508
535
|
|
|
509
536
|
users
|
|
510
537
|
.command(`updateStatus`)
|
|
511
|
-
.description(`Update the user status by its unique ID.`)
|
|
538
|
+
.description(`Update the user status by its unique ID. Use this endpoint as an alternative to deleting a user if you want to keep user's ID reserved.`)
|
|
512
539
|
.requiredOption(`--userId <userId>`, `User ID.`)
|
|
513
540
|
.requiredOption(`--status <status>`, `User Status. To activate the user pass 'true' and to block the user pass 'false'.`, parseBool)
|
|
514
541
|
.action(actionRunner(usersUpdateStatus))
|
|
@@ -530,6 +557,7 @@ module.exports = {
|
|
|
530
557
|
usersDelete,
|
|
531
558
|
usersUpdateEmail,
|
|
532
559
|
usersGetLogs,
|
|
560
|
+
usersGetMemberships,
|
|
533
561
|
usersUpdateName,
|
|
534
562
|
usersUpdatePassword,
|
|
535
563
|
usersGetPrefs,
|
|
@@ -539,4 +567,4 @@ module.exports = {
|
|
|
539
567
|
usersDeleteSession,
|
|
540
568
|
usersUpdateStatus,
|
|
541
569
|
usersUpdateVerification
|
|
542
|
-
};
|
|
570
|
+
};
|