appwrite-cli 5.0.3 → 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 (54) 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/messaging/update-email.md +1 -0
  9. package/docs/examples/projects/create-j-w-t.md +4 -0
  10. package/docs/examples/projects/update-mock-numbers.md +3 -0
  11. package/docs/examples/projects/update-session-alerts.md +3 -0
  12. package/docs/examples/users/create-j-w-t.md +4 -0
  13. package/docs/examples/vcs/get-repository-contents.md +4 -0
  14. package/index.js +34 -7
  15. package/install.ps1 +3 -3
  16. package/install.sh +2 -2
  17. package/lib/client.js +19 -5
  18. package/lib/commands/account.js +307 -153
  19. package/lib/commands/assistant.js +8 -5
  20. package/lib/commands/avatars.js +116 -60
  21. package/lib/commands/console.js +8 -5
  22. package/lib/commands/databases.js +353 -164
  23. package/lib/commands/functions.js +310 -100
  24. package/lib/commands/generic.js +206 -54
  25. package/lib/commands/graphql.js +14 -8
  26. package/lib/commands/health.js +140 -71
  27. package/lib/commands/init.js +250 -155
  28. package/lib/commands/locale.js +50 -26
  29. package/lib/commands/messaging.js +363 -179
  30. package/lib/commands/migrations.js +98 -50
  31. package/lib/commands/project.js +38 -20
  32. package/lib/commands/projects.js +449 -144
  33. package/lib/commands/proxy.js +32 -17
  34. package/lib/commands/pull.js +231 -0
  35. package/lib/commands/push.js +1518 -0
  36. package/lib/commands/run.js +282 -0
  37. package/lib/commands/storage.js +160 -76
  38. package/lib/commands/teams.js +102 -50
  39. package/lib/commands/users.js +325 -135
  40. package/lib/commands/vcs.js +102 -29
  41. package/lib/config.js +190 -18
  42. package/lib/emulation/docker.js +187 -0
  43. package/lib/emulation/utils.js +177 -0
  44. package/lib/id.js +30 -0
  45. package/lib/paginate.js +1 -2
  46. package/lib/parser.js +69 -12
  47. package/lib/questions.js +462 -84
  48. package/lib/sdks.js +1 -1
  49. package/lib/spinner.js +103 -0
  50. package/lib/utils.js +248 -3
  51. package/lib/validations.js +17 -0
  52. package/package.json +6 -2
  53. package/scoop/appwrite.json +3 -3
  54. package/lib/commands/deploy.js +0 -941
@@ -3,20 +3,44 @@ const { Command } = require("commander");
3
3
  const Client = require("../client");
4
4
  const { sdkForConsole } = require("../sdks");
5
5
  const { globalConfig, localConfig } = require("../config");
6
- const { actionRunner, success, parseBool, commandDescriptions, log, parse } = require("../parser");
7
- const { questionsLogin, questionsListFactors, questionsMfaChallenge } = require("../questions");
8
- const { accountUpdateMfaChallenge, accountCreateMfaChallenge, accountGet, accountCreateEmailPasswordSession, accountDeleteSession } = require("./account");
6
+ const { actionRunner, success, parseBool, commandDescriptions, error, parse, log, drawTable, cliConfig } = require("../parser");
7
+ const ID = require("../id");
8
+ const { questionsLogin, questionsLogout, questionsListFactors, questionsMfaChallenge } = require("../questions");
9
+ const { accountUpdateMfaChallenge, accountCreateMfaChallenge, accountGet, accountCreateEmailPasswordSession, accountDeleteSession } = require("./account");
9
10
 
10
- const login = new Command("login")
11
- .description(commandDescriptions['login'])
12
- .configureHelp({
13
- helpWidth: process.stdout.columns || 80
14
- })
15
- .action(actionRunner(async () => {
16
- const answers = await inquirer.prompt(questionsLogin)
11
+ const DEFAULT_ENDPOINT = 'https://cloud.appwrite.io/v1';
17
12
 
18
- let client = await sdkForConsole(false);
13
+ const loginCommand = async ({ email, password, endpoint, mfa, code }) => {
14
+ const oldCurrent = globalConfig.getCurrentSession();
15
+ let configEndpoint = endpoint ?? DEFAULT_ENDPOINT;
16
+
17
+ const answers = email && password ? { email, password } : await inquirer.prompt(questionsLogin);
18
+
19
+ if (answers.method === 'select') {
20
+ const accountId = answers.accountId;
21
+
22
+ if (!globalConfig.getSessionIds().includes(accountId)) {
23
+ throw Error('Session ID not found');
24
+ }
25
+
26
+ globalConfig.setCurrentSession(accountId);
27
+ success(`Current account is ${accountId}`);
28
+
29
+ return;
30
+ }
31
+
32
+ const id = ID.unique();
33
+
34
+ globalConfig.addSession(id, {});
35
+ globalConfig.setCurrentSession(id);
36
+ globalConfig.setEndpoint(configEndpoint);
37
+ globalConfig.setEmail(answers.email);
19
38
 
39
+ let client = await sdkForConsole(false);
40
+
41
+ let account;
42
+
43
+ try {
20
44
  await accountCreateEmailPasswordSession({
21
45
  email: answers.email,
22
46
  password: answers.password,
@@ -26,6 +50,57 @@ const login = new Command("login")
26
50
 
27
51
  client.setCookie(globalConfig.getCookie());
28
52
 
53
+ account = await accountGet({
54
+ sdk: client,
55
+ parseOutput: false
56
+ });
57
+ } catch (error) {
58
+ if (error.response === 'user_more_factors_required') {
59
+ const { factor } = mfa ? { factor: mfa } : await inquirer.prompt(questionsListFactors);
60
+
61
+ const challenge = await accountCreateMfaChallenge({
62
+ factor,
63
+ parseOutput: false,
64
+ sdk: client
65
+ });
66
+
67
+ const { otp } = code ? { otp: code } : await inquirer.prompt(questionsMfaChallenge);
68
+
69
+ await accountUpdateMfaChallenge({
70
+ challengeId: challenge.$id,
71
+ otp,
72
+ parseOutput: false,
73
+ sdk: client
74
+ });
75
+
76
+ account = await accountGet({
77
+ sdk: client,
78
+ parseOutput: false
79
+ });
80
+ } else {
81
+ globalConfig.removeSession(id);
82
+ globalConfig.setCurrentSession(oldCurrent);
83
+ if(endpoint !== DEFAULT_ENDPOINT && error.response === 'user_invalid_credentials'){
84
+ log('Use the --endpoint option for self-hosted instances')
85
+ }
86
+ throw error;
87
+ }
88
+ }
89
+
90
+ success("Signed in as user with ID: " + account.$id);
91
+ log("Next you can create or link to your project using 'appwrite init project'");
92
+ };
93
+
94
+ const whoami = new Command("whoami")
95
+ .description(commandDescriptions['whoami'])
96
+ .action(actionRunner(async () => {
97
+ if (globalConfig.getEndpoint() === '' || globalConfig.getCookie() === '') {
98
+ error("No user is signed in. To sign in, run: appwrite login ");
99
+ return;
100
+ }
101
+
102
+ let client = await sdkForConsole(false);
103
+
29
104
  let account;
30
105
 
31
106
  try {
@@ -33,43 +108,49 @@ const login = new Command("login")
33
108
  sdk: client,
34
109
  parseOutput: false
35
110
  });
36
- } catch(error) {
37
- if (error.response === 'user_more_factors_required') {
38
- const { factor } = await inquirer.prompt(questionsListFactors);
39
-
40
- const challenge = await accountCreateMfaChallenge({
41
- factor,
42
- parseOutput: false,
43
- sdk: client
44
- });
45
-
46
- const { otp } = await inquirer.prompt(questionsMfaChallenge);
47
-
48
- await accountUpdateMfaChallenge({
49
- challengeId: challenge.$id,
50
- otp,
51
- parseOutput: false,
52
- sdk: client
53
- });
54
-
55
- account = await accountGet({
56
- sdk: client,
57
- parseOutput: false
58
- });
59
- } else {
60
- throw error;
111
+ } catch (error) {
112
+ error("No user is signed in. To sign in, run: appwrite login");
113
+ return;
114
+ }
115
+
116
+ const data = [
117
+ {
118
+ 'ID': account.$id,
119
+ 'Name': account.name,
120
+ 'Email': account.email,
121
+ 'MFA enabled': account.mfa ? 'Yes' : 'No',
122
+ 'Endpoint': globalConfig.getEndpoint()
61
123
  }
124
+ ];
125
+
126
+ if(cliConfig.json) {
127
+ console.log(data);
128
+ return;
62
129
  }
63
130
 
64
- success("Signed in as user with ID: " + account.$id);
131
+ drawTable(data)
65
132
  }));
66
133
 
67
- const logout = new Command("logout")
68
- .description(commandDescriptions['logout'])
134
+ const register = new Command("register")
135
+ .description(commandDescriptions['register'])
136
+ .action(actionRunner(async () => {
137
+ log('Visit https://cloud.appwrite.io/register to create an account')
138
+ }));
139
+
140
+ const login = new Command("login")
141
+ .description(commandDescriptions['login'])
142
+ .option(`--email [email]`, `User email`)
143
+ .option(`--password [password]`, `User password`)
144
+ .option(`--endpoint [endpoint]`, `Appwrite endpoint for self hosted instances`)
145
+ .option(`--mfa [factor]`, `Multi-factor authentication login factor: totp, email, phone or recoveryCode`)
146
+ .option(`--code [code]`, `Multi-factor code`)
69
147
  .configureHelp({
70
148
  helpWidth: process.stdout.columns || 80
71
149
  })
72
- .action(actionRunner(async () => {
150
+ .action(actionRunner(loginCommand));
151
+
152
+ const deleteSession = async (accountId) => {
153
+ try {
73
154
  let client = await sdkForConsole();
74
155
 
75
156
  await accountDeleteSession({
@@ -78,8 +159,51 @@ const logout = new Command("logout")
78
159
  sdk: client
79
160
  })
80
161
 
81
- globalConfig.setCookie("");
82
- success()
162
+ globalConfig.removeSession(accountId);
163
+ } catch (e) {
164
+ error('Unable to log out, removing locally saved session information')
165
+ }
166
+ globalConfig.removeSession(accountId);
167
+ }
168
+
169
+ const logout = new Command("logout")
170
+ .description(commandDescriptions['logout'])
171
+ .configureHelp({
172
+ helpWidth: process.stdout.columns || 80
173
+ })
174
+ .action(actionRunner(async () => {
175
+ const sessions = globalConfig.getSessions();
176
+ const current = globalConfig.getCurrentSession();
177
+
178
+ if (current === '') {
179
+ return;
180
+ }
181
+ if (sessions.length === 1) {
182
+ await deleteSession(current);
183
+ success();
184
+
185
+ return;
186
+ }
187
+
188
+ const answers = await inquirer.prompt(questionsLogout);
189
+
190
+ if (answers.accounts) {
191
+ for (let accountId of answers.accounts) {
192
+ globalConfig.setCurrentSession(accountId);
193
+ await deleteSession(accountId);
194
+ }
195
+ }
196
+
197
+ const remainingSessions = globalConfig.getSessions();
198
+
199
+ if (remainingSessions .length > 0 && remainingSessions .filter(session => session.id === current).length !== 1) {
200
+ const accountId = remainingSessions [0].id;
201
+ globalConfig.setCurrentSession(accountId);
202
+
203
+ success(`Current account is ${accountId}`);
204
+ }
205
+
206
+ success();
83
207
  }));
84
208
 
85
209
  const client = new Command("client")
@@ -87,12 +211,12 @@ const client = new Command("client")
87
211
  .configureHelp({
88
212
  helpWidth: process.stdout.columns || 80
89
213
  })
90
- .option("--selfSigned <value>", "Configure the CLI to use a self-signed certificate ( true or false )", parseBool)
91
- .option("--endpoint <endpoint>", "Set your Appwrite server endpoint")
92
- .option("--projectId <projectId>", "Set your Appwrite project ID")
93
- .option("--key <key>", "Set your Appwrite server's API key")
94
- .option("--debug", "Print CLI debug information")
95
- .option("--reset", "Reset the CLI configuration")
214
+ .option("-ss, --selfSigned <value>", "Configure the CLI to use a self-signed certificate ( true or false )", parseBool)
215
+ .option("-e, --endpoint <endpoint>", "Set your Appwrite server endpoint")
216
+ .option("-p, --projectId <projectId>", "Set your Appwrite project ID")
217
+ .option("-k, --key <key>", "Set your Appwrite server's API key")
218
+ .option("-d, --debug", "Print CLI debug information")
219
+ .option("-r, --reset", "Reset the CLI configuration")
96
220
  .action(actionRunner(async ({ selfSigned, endpoint, projectId, key, debug, reset }, command) => {
97
221
  if (selfSigned == undefined && endpoint == undefined && projectId == undefined && key == undefined && debug == undefined && reset == undefined) {
98
222
  command.help()
@@ -111,6 +235,7 @@ const client = new Command("client")
111
235
 
112
236
  if (endpoint !== undefined) {
113
237
  try {
238
+ const id = ID.unique();
114
239
  let url = new URL(endpoint);
115
240
  if (url.protocol !== "http:" && url.protocol !== "https:") {
116
241
  throw new Error();
@@ -125,7 +250,8 @@ const client = new Command("client")
125
250
  if (!response.version) {
126
251
  throw new Error();
127
252
  }
128
-
253
+ globalConfig.setCurrentSession(id);
254
+ globalConfig.addSession(id, {});
129
255
  globalConfig.setEndpoint(endpoint);
130
256
  } catch (_) {
131
257
  throw new Error("Invalid endpoint or your Appwrite server is not running as expected.");
@@ -145,18 +271,44 @@ const client = new Command("client")
145
271
  }
146
272
 
147
273
  if (reset !== undefined) {
148
- globalConfig.setEndpoint("");
149
- globalConfig.setKey("");
150
- globalConfig.setCookie("");
151
- globalConfig.setSelfSigned("");
152
- localConfig.setProject("", "");
274
+ const sessions = globalConfig.getSessions();
275
+
276
+ for (let accountId of sessions.map(session => session.id)) {
277
+ globalConfig.setCurrentSession(accountId);
278
+ await deleteSession(accountId);
279
+ }
153
280
  }
154
281
 
155
282
  success()
156
283
  }));
157
284
 
285
+ const migrate = async () => {
286
+ if (!globalConfig.has('endpoint') || !globalConfig.has('cookie')) {
287
+ return;
288
+ }
289
+
290
+ const endpoint = globalConfig.get('endpoint');
291
+ const cookie = globalConfig.get('cookie');
292
+
293
+ const id = ID.unique();
294
+ const data = {
295
+ endpoint,
296
+ cookie,
297
+ email: 'legacy'
298
+ };
299
+
300
+ globalConfig.addSession(id, data);
301
+ globalConfig.setCurrentSession(id);
302
+ globalConfig.delete('endpoint');
303
+ globalConfig.delete('cookie');
304
+
305
+ }
158
306
  module.exports = {
307
+ loginCommand,
308
+ whoami,
309
+ register,
159
310
  login,
160
311
  logout,
312
+ migrate,
161
313
  client
162
314
  };
@@ -4,7 +4,7 @@ const tar = require("tar");
4
4
  const ignore = require("ignore");
5
5
  const { promisify } = require('util');
6
6
  const libClient = require('../client.js');
7
- const { getAllFiles } = require('../utils.js');
7
+ const { getAllFiles, showConsoleLink } = require('../utils.js');
8
8
  const { Command } = require('commander');
9
9
  const { sdkForProject, sdkForConsole } = require('../sdks')
10
10
  const { parse, actionRunner, parseInteger, parseBool, commandDescriptions, success, log } = require('../parser')
@@ -42,6 +42,7 @@ const graphql = new Command("graphql").description(commandDescriptions['graphql'
42
42
  /**
43
43
  * @typedef {Object} GraphqlQueryRequestParams
44
44
  * @property {object} query The query or queries to execute.
45
+ * @property {boolean} overrideForCli
45
46
  * @property {boolean} parseOutput
46
47
  * @property {libClient | undefined} sdk
47
48
  */
@@ -49,8 +50,9 @@ const graphql = new Command("graphql").description(commandDescriptions['graphql'
49
50
  /**
50
51
  * @param {GraphqlQueryRequestParams} params
51
52
  */
52
- const graphqlQuery = async ({ query, parseOutput = true, sdk = undefined}) => {
53
- let client = !sdk ? await sdkForProject() : sdk;
53
+ const graphqlQuery = async ({query,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
54
+ let client = !sdk ? await sdkForProject() :
55
+ sdk;
54
56
  let apiPath = '/graphql';
55
57
  let payload = {};
56
58
  if (typeof query !== 'undefined') {
@@ -68,13 +70,15 @@ const graphqlQuery = async ({ query, parseOutput = true, sdk = undefined}) => {
68
70
  parse(response)
69
71
  success()
70
72
  }
71
-
73
+
72
74
  return response;
75
+
73
76
  }
74
77
 
75
78
  /**
76
79
  * @typedef {Object} GraphqlMutationRequestParams
77
80
  * @property {object} query The query or queries to execute.
81
+ * @property {boolean} overrideForCli
78
82
  * @property {boolean} parseOutput
79
83
  * @property {libClient | undefined} sdk
80
84
  */
@@ -82,8 +86,9 @@ const graphqlQuery = async ({ query, parseOutput = true, sdk = undefined}) => {
82
86
  /**
83
87
  * @param {GraphqlMutationRequestParams} params
84
88
  */
85
- const graphqlMutation = async ({ query, parseOutput = true, sdk = undefined}) => {
86
- let client = !sdk ? await sdkForProject() : sdk;
89
+ const graphqlMutation = async ({query,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
90
+ let client = !sdk ? await sdkForProject() :
91
+ sdk;
87
92
  let apiPath = '/graphql/mutation';
88
93
  let payload = {};
89
94
  if (typeof query !== 'undefined') {
@@ -101,8 +106,9 @@ const graphqlMutation = async ({ query, parseOutput = true, sdk = undefined}) =>
101
106
  parse(response)
102
107
  success()
103
108
  }
104
-
109
+
105
110
  return response;
111
+
106
112
  }
107
113
 
108
114
  graphql
@@ -121,4 +127,4 @@ module.exports = {
121
127
  graphql,
122
128
  graphqlQuery,
123
129
  graphqlMutation
124
- };
130
+ };