appwrite-cli 6.0.0-rc.1 → 6.0.0-rc.2

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/README.md CHANGED
@@ -29,7 +29,7 @@ Once the installation is complete, you can verify the install using
29
29
 
30
30
  ```sh
31
31
  $ appwrite -v
32
- 6.0.0-rc.1
32
+ 6.0.0-rc.2
33
33
  ```
34
34
 
35
35
  ### Install using prebuilt binaries
@@ -60,7 +60,7 @@ $ scoop install https://raw.githubusercontent.com/appwrite/sdk-for-cli/master/sc
60
60
  Once the installation completes, you can verify your install using
61
61
  ```
62
62
  $ appwrite -v
63
- 6.0.0-rc.1
63
+ 6.0.0-rc.2
64
64
  ```
65
65
 
66
66
  ## Getting Started
package/index.js CHANGED
@@ -15,7 +15,7 @@ const { login, logout, whoami, migrate, register } = require("./lib/commands/gen
15
15
  const { init } = require("./lib/commands/init");
16
16
  const { pull } = require("./lib/commands/pull");
17
17
  const { run } = require("./lib/commands/run");
18
- const { push } = require("./lib/commands/push");
18
+ const { push, deploy } = require("./lib/commands/push");
19
19
  const { account } = require("./lib/commands/account");
20
20
  const { avatars } = require("./lib/commands/avatars");
21
21
  const { assistant } = require("./lib/commands/assistant");
@@ -77,6 +77,7 @@ program
77
77
  .addCommand(init)
78
78
  .addCommand(pull)
79
79
  .addCommand(push)
80
+ .addCommand(deploy)
80
81
  .addCommand(run)
81
82
  .addCommand(logout)
82
83
  .addCommand(account)
package/install.ps1 CHANGED
@@ -13,8 +13,8 @@
13
13
  # You can use "View source" of this page to see the full script.
14
14
 
15
15
  # REPO
16
- $GITHUB_x64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/6.0.0-rc.1/appwrite-cli-win-x64.exe"
17
- $GITHUB_arm64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/6.0.0-rc.1/appwrite-cli-win-arm64.exe"
16
+ $GITHUB_x64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/6.0.0-rc.2/appwrite-cli-win-x64.exe"
17
+ $GITHUB_arm64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/6.0.0-rc.2/appwrite-cli-win-arm64.exe"
18
18
 
19
19
  $APPWRITE_BINARY_NAME = "appwrite.exe"
20
20
 
package/install.sh CHANGED
@@ -97,7 +97,7 @@ printSuccess() {
97
97
  downloadBinary() {
98
98
  echo "[2/4] Downloading executable for $OS ($ARCH) ..."
99
99
 
100
- GITHUB_LATEST_VERSION="6.0.0-rc.1"
100
+ GITHUB_LATEST_VERSION="6.0.0-rc.2"
101
101
  GITHUB_FILE="appwrite-cli-${OS}-${ARCH}"
102
102
  GITHUB_URL="https://github.com/$GITHUB_REPOSITORY_NAME/releases/download/$GITHUB_LATEST_VERSION/$GITHUB_FILE"
103
103
 
package/lib/client.js CHANGED
@@ -16,8 +16,8 @@ class Client {
16
16
  'x-sdk-name': 'Command Line',
17
17
  'x-sdk-platform': 'console',
18
18
  'x-sdk-language': 'cli',
19
- 'x-sdk-version': '6.0.0-rc.1',
20
- 'user-agent' : `AppwriteCLI/6.0.0-rc.1 (${os.type()} ${os.version()}; ${os.arch()})`,
19
+ 'x-sdk-version': '6.0.0-rc.2',
20
+ 'user-agent' : `AppwriteCLI/6.0.0-rc.2 (${os.type()} ${os.version()}; ${os.arch()})`,
21
21
  'X-Appwrite-Response-Format' : '1.5.0',
22
22
  };
23
23
  }
@@ -3,7 +3,7 @@ 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, error, parse, log, drawTable, cliConfig } = require("../parser");
6
+ const { actionRunner, success, parseBool, commandDescriptions, error, parse, hint, log, drawTable, cliConfig } = require("../parser");
7
7
  const ID = require("../id");
8
8
  const { questionsLogin, questionsLogout, questionsListFactors, questionsMfaChallenge } = require("../questions");
9
9
  const { accountUpdateMfaChallenge, accountCreateMfaChallenge, accountGet, accountCreateEmailPasswordSession, accountDeleteSession } = require("./account");
@@ -14,8 +14,20 @@ const loginCommand = async ({ email, password, endpoint, mfa, code }) => {
14
14
  const oldCurrent = globalConfig.getCurrentSession();
15
15
  let configEndpoint = endpoint ?? DEFAULT_ENDPOINT;
16
16
 
17
+ if(globalConfig.getCurrentSession() !== '') {
18
+ log('You are currently signed in as ' + globalConfig.getEmail());
19
+
20
+ if(globalConfig.getSessions().length === 1) {
21
+ hint('You can sign in and manage multiple accounts with Appwrite CLI');
22
+ }
23
+ }
24
+
17
25
  const answers = email && password ? { email, password } : await inquirer.prompt(questionsLogin);
18
26
 
27
+ if(!answers.method) {
28
+ answers.method = 'login';
29
+ }
30
+
19
31
  if (answers.method === 'select') {
20
32
  const accountId = answers.accountId;
21
33
 
@@ -87,15 +99,15 @@ const loginCommand = async ({ email, password, endpoint, mfa, code }) => {
87
99
  }
88
100
  }
89
101
 
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'");
102
+ success("Successfully signed in as " + account.email);
103
+ hint("Next you can create or link to your project using 'appwrite init project'");
92
104
  };
93
105
 
94
106
  const whoami = new Command("whoami")
95
107
  .description(commandDescriptions['whoami'])
96
108
  .action(actionRunner(async () => {
97
109
  if (globalConfig.getEndpoint() === '' || globalConfig.getCookie() === '') {
98
- error("No user is signed in. To sign in, run: appwrite login ");
110
+ error("No user is signed in. To sign in, run 'appwrite login'");
99
111
  return;
100
112
  }
101
113
 
@@ -109,7 +121,7 @@ const whoami = new Command("whoami")
109
121
  parseOutput: false
110
122
  });
111
123
  } catch (error) {
112
- error("No user is signed in. To sign in, run: appwrite login");
124
+ error("No user is signed in. To sign in, run 'appwrite login'");
113
125
  return;
114
126
  }
115
127
 
@@ -9,6 +9,7 @@ const { storageCreateBucket } = require("./storage");
9
9
  const { messagingCreateTopic } = require("./messaging");
10
10
  const { functionsCreate } = require("./functions");
11
11
  const { databasesCreateCollection } = require("./databases");
12
+ const { pullResources } = require("./pull");
12
13
  const ID = require("../id");
13
14
  const { localConfig, globalConfig } = require("../config");
14
15
  const {
@@ -18,10 +19,11 @@ const {
18
19
  questionsCreateMessagingTopic,
19
20
  questionsCreateCollection,
20
21
  questionsInitProject,
22
+ questionsInitProjectAutopull,
21
23
  questionsInitResources,
22
24
  questionsCreateTeam
23
25
  } = require("../questions");
24
- const { success, log, error, actionRunner, commandDescriptions } = require("../parser");
26
+ const { cliConfig, success, log, hint, error, actionRunner, commandDescriptions } = require("../parser");
25
27
  const { accountGet } = require("./account");
26
28
  const { sdkForConsole } = require("../sdks");
27
29
 
@@ -56,7 +58,7 @@ const initProject = async ({ organizationId, projectId, projectName } = {}) => {
56
58
  sdk: client
57
59
  });
58
60
  } catch (e) {
59
- error('Error Session not found. Please run `appwrite login` to create a session');
61
+ error("Error Session not found. Please run 'appwrite login' to create a session");
60
62
  process.exit(1);
61
63
  }
62
64
 
@@ -104,11 +106,17 @@ const initProject = async ({ organizationId, projectId, projectName } = {}) => {
104
106
 
105
107
  success(`Project successfully ${answers.start === 'existing' ? 'linked' : 'created'}. Details are now stored in appwrite.json file.`);
106
108
 
107
- log("Next you can use 'appwrite init' to create resources in your project, or use 'appwrite pull' and 'appwite push' to synchronize your project.")
108
-
109
109
  if(answers.start === 'existing') {
110
- log("Since you connected to an existing project, we highly recommend to run 'appwrite pull all' to synchronize all of your existing resources.");
110
+ answers = await inquirer.prompt(questionsInitProjectAutopull);
111
+ if(answers.autopull) {
112
+ cliConfig.all = true;
113
+ await pullResources();
114
+ } else {
115
+ log("You can run 'appwrite pull all' to synchronize all of your existing resources.");
116
+ }
111
117
  }
118
+
119
+ hint("Next you can use 'appwrite init' to create resources in your project, or use 'appwrite pull' and 'appwrite push' to synchronize your project.")
112
120
  }
113
121
 
114
122
  const initBucket = async () => {
@@ -210,22 +218,24 @@ const initFunction = async () => {
210
218
  log(`Installation command for this runtime not found. You will be asked to configure the install command when you first push the function.`);
211
219
  }
212
220
 
213
-
214
221
  fs.mkdirSync(functionDir, "777");
215
222
  fs.mkdirSync(templatesDir, "777");
216
223
  const repo = "https://github.com/appwrite/templates";
217
224
  const api = `https://api.github.com/repos/appwrite/templates/contents/${answers.runtime.name}`
218
- const templates = ['starter'];
219
225
  let selected = undefined;
220
226
 
221
- try {
222
- const res = await fetch(api);
223
- templates.push(...(await res.json()).map((template) => template.name));
224
-
225
- selected = await inquirer.prompt(questionsCreateFunctionSelectTemplate(templates))
226
- } catch {
227
- // Not a problem will go with directory pulling
228
- log('Loading templates...');
227
+ if(answers.template === 'starter') {
228
+ selected = { template: 'starter' };
229
+ } else {
230
+ try {
231
+ const res = await fetch(api);
232
+ const templates = [];
233
+ templates.push(...(await res.json()).map((template) => template.name));
234
+ selected = await inquirer.prompt(questionsCreateFunctionSelectTemplate(templates));
235
+ } catch {
236
+ // Not a problem will go with directory pulling
237
+ log('Loading templates...');
238
+ }
229
239
  }
230
240
 
231
241
  const sparse = (selected ? `${answers.runtime.name}/${selected.template}` : answers.runtime.name).toLowerCase();
@@ -257,6 +267,7 @@ const initFunction = async () => {
257
267
 
258
268
  fs.rmSync(path.join(templatesDir, ".git"), { recursive: true });
259
269
  if (!selected) {
270
+ const templates = [];
260
271
  templates.push(...fs.readdirSync(runtimeDir, { withFileTypes: true })
261
272
  .filter(item => item.isDirectory() && item.name !== 'starter')
262
273
  .map(dirent => dirent.name));
@@ -1,4 +1,5 @@
1
1
  const fs = require("fs");
2
+ const chalk = require('chalk');
2
3
  const tar = require("tar");
3
4
  const { Command } = require("commander");
4
5
  const inquirer = require("inquirer");
@@ -11,11 +12,11 @@ const { storageListBuckets } = require("./storage");
11
12
  const { localConfig } = require("../config");
12
13
  const { paginate } = require("../paginate");
13
14
  const { questionsPullCollection, questionsPullFunctions, questionsPullResources } = require("../questions");
14
- const { cliConfig, success, log, actionRunner, commandDescriptions } = require("../parser");
15
+ const { cliConfig, success, log, warn, actionRunner, commandDescriptions } = require("../parser");
15
16
 
16
17
  const pullResources = async () => {
17
18
  const actions = {
18
- project: pullProject,
19
+ settings: pullSettings,
19
20
  functions: pullFunctions,
20
21
  collections: pullCollection,
21
22
  buckets: pullBucket,
@@ -25,6 +26,7 @@ const pullResources = async () => {
25
26
 
26
27
  if (cliConfig.all) {
27
28
  for (let action of Object.values(actions)) {
29
+ cliConfig.all = true;
28
30
  await action();
29
31
  }
30
32
  } else {
@@ -37,75 +39,94 @@ const pullResources = async () => {
37
39
  }
38
40
  };
39
41
 
40
- const pullProject = async () => {
42
+ const pullSettings = async () => {
43
+ log("Pulling project settings ...");
44
+
41
45
  try {
42
46
  let response = await projectsGet({
43
47
  parseOutput: false,
44
48
  projectId: localConfig.getProject().projectId
45
-
46
- })
49
+ });
47
50
 
48
51
  localConfig.setProject(response.$id, response.name, response);
49
52
 
50
- success();
53
+ success(`Successfully pulled ${chalk.bold('all')} project settings.`);
51
54
  } catch (e) {
52
55
  throw e;
53
56
  }
54
57
  }
55
58
 
56
59
  const pullFunctions = async () => {
57
- const localFunctions = localConfig.getFunctions();
60
+ log("Fetching functions ...");
61
+ let total = 0;
62
+
63
+ const fetchResponse = await functionsList({
64
+ queries: [JSON.stringify({ method: 'limit', values: [1] })],
65
+ parseOutput: false
66
+ });
67
+ if (fetchResponse["functions"].length <= 0) {
68
+ log("No functions found.");
69
+ success(`Successfully pulled ${chalk.bold(total)} functions.`);
70
+ return;
71
+ }
58
72
 
59
73
  const functions = cliConfig.all
60
74
  ? (await paginate(functionsList, { parseOutput: false }, 100, 'functions')).functions
61
75
  : (await inquirer.prompt(questionsPullFunctions)).functions;
62
76
 
63
- log(`Pulling ${functions.length} functions`);
64
-
65
77
  for (let func of functions) {
66
- const functionExistLocally = localFunctions.find((localFunc) => localFunc['$id'] === func['$id']) !== undefined;
78
+ total++;
79
+ log(`Pulling function ${chalk.bold(func['name'])} ...`);
67
80
 
68
- if (functionExistLocally) {
69
- localConfig.updateFunction(func['$id'], func);
70
- } else {
71
- func['path'] = `functions/${func['$id']}`;
72
- localConfig.addFunction(func);
73
- localFunctions.push(func);
81
+ const localFunction = localConfig.getFunction(func.$id);
82
+ if(!localFunction['path']) {
83
+ func['path'] = `functions/${func.$id}`;
74
84
  }
75
85
 
76
- const localFunction = localFunctions.find((localFunc) => localFunc['$id'] === func['$id']);
86
+ localConfig.addFunction(func);
77
87
 
78
- if (localFunction['deployment'] === '') {
79
- continue
88
+ if (!fs.existsSync(func['path'])) {
89
+ fs.mkdirSync(func['path'], { recursive: true });
80
90
  }
81
91
 
82
- const compressedFileName = `${func['$id']}-${+new Date()}.tar.gz`
92
+ if(func['deployment']) {
93
+ const compressedFileName = `${func['$id']}-${+new Date()}.tar.gz`
94
+ await functionsDownloadDeployment({
95
+ functionId: func['$id'],
96
+ deploymentId: func['deployment'],
97
+ destination: compressedFileName,
98
+ overrideForCli: true,
99
+ parseOutput: false
100
+ });
83
101
 
84
- await functionsDownloadDeployment({
85
- functionId: func['$id'],
86
- deploymentId: func['deployment'],
87
- destination: compressedFileName,
88
- overrideForCli: true,
89
- parseOutput: false
90
- })
102
+ tar.extract({
103
+ sync: true,
104
+ cwd: func['path'],
105
+ file: compressedFileName,
106
+ strict: false,
107
+ });
91
108
 
92
- if (!fs.existsSync(localFunction['path'])) {
93
- fs.mkdirSync(localFunction['path'], { recursive: true });
109
+ fs.rmSync(compressedFileName);
94
110
  }
95
-
96
- tar.extract({
97
- sync: true,
98
- cwd: localFunction['path'],
99
- file: compressedFileName,
100
- strict: false,
101
- });
102
-
103
- fs.rmSync(compressedFileName);
104
- success(`Pulled ${func['name']} code and settings`)
105
111
  }
112
+
113
+ success(`Successfully pulled ${chalk.bold(total)} functions.`);
106
114
  }
107
115
 
108
116
  const pullCollection = async () => {
117
+ log("Fetching collections ...");
118
+ let total = 0;
119
+
120
+ const fetchResponse = await databasesList({
121
+ queries: [JSON.stringify({ method: 'limit', values: [1] })],
122
+ parseOutput: false
123
+ });
124
+ if (fetchResponse["databases"].length <= 0) {
125
+ log("No collections found.");
126
+ success(`Successfully pulled ${chalk.bold(total)} collections.`);
127
+ return;
128
+ }
129
+
109
130
  let databases = cliConfig.ids;
110
131
 
111
132
  if (databases.length === 0) {
@@ -122,61 +143,101 @@ const pullCollection = async () => {
122
143
  parseOutput: false
123
144
  });
124
145
 
146
+ total++;
147
+ log(`Pulling all collections from ${chalk.bold(database['name'])} database ...`);
148
+
125
149
  localConfig.addDatabase(database);
126
150
 
127
- const { collections, total } = await paginate(databasesListCollections, {
151
+ const { collections } = await paginate(databasesListCollections, {
128
152
  databaseId,
129
153
  parseOutput: false
130
154
  }, 100, 'collections');
131
155
 
132
- log(`Found ${total} collections`);
133
-
134
- collections.map(async collection => {
135
- log(`Fetching ${collection.name} ...`);
156
+ for(const collection of collections) {
136
157
  localConfig.addCollection({
137
158
  ...collection,
138
159
  '$createdAt': undefined,
139
160
  '$updatedAt': undefined
140
161
  });
141
- });
162
+ }
142
163
  }
143
164
 
144
- success();
165
+ success(`Successfully pulled ${chalk.bold(total)} collections.`);
145
166
  }
146
167
 
147
168
  const pullBucket = async () => {
148
- const { buckets } = await paginate(storageListBuckets, { parseOutput: false }, 100, 'buckets');
169
+ log("Fetching buckets ...");
170
+ let total = 0;
149
171
 
150
- log(`Found ${buckets.length} buckets`);
172
+ const fetchResponse = await storageListBuckets({
173
+ queries: [JSON.stringify({ method: 'limit', values: [1] })],
174
+ parseOutput: false
175
+ });
176
+ if (fetchResponse["buckets"].length <= 0) {
177
+ log("No buckets found.");
178
+ success(`Successfully pulled ${chalk.bold(total)} buckets.`);
179
+ return;
180
+ }
151
181
 
152
- buckets.forEach(bucket => localConfig.addBucket(bucket));
182
+ const { buckets } = await paginate(storageListBuckets, { parseOutput: false }, 100, 'buckets');
153
183
 
154
- success();
184
+ for(const bucket of buckets) {
185
+ total++;
186
+ log(`Pulling bucket ${chalk.bold(bucket['name'])} ...`);
187
+ localConfig.addBucket(bucket);
188
+ }
189
+
190
+ success(`Successfully pulled ${chalk.bold(total)} buckets.`);
155
191
  }
156
192
 
157
193
  const pullTeam = async () => {
158
- const { teams } = await paginate(teamsList, { parseOutput: false }, 100, 'teams');
159
-
160
- log(`Found ${teams.length} teams`);
194
+ log("Fetching teams ...");
195
+ let total = 0;
161
196
 
162
- teams.forEach(team => {
163
- const { total, $updatedAt, $createdAt, prefs, ...rest } = team;
164
- localConfig.addTeam(rest);
197
+ const fetchResponse = await teamsList({
198
+ queries: [JSON.stringify({ method: 'limit', values: [1] })],
199
+ parseOutput: false
165
200
  });
201
+ if (fetchResponse["teams"].length <= 0) {
202
+ log("No teams found.");
203
+ success(`Successfully pulled ${chalk.bold(total)} teams.`);
204
+ return;
205
+ }
166
206
 
167
- success();
207
+ const { teams } = await paginate(teamsList, { parseOutput: false }, 100, 'teams');
208
+
209
+ for(const team of teams) {
210
+ total++;
211
+ log(`Pulling team ${chalk.bold(team['name'])} ...`);
212
+ localConfig.addTeam(team);
213
+ }
214
+
215
+ success(`Successfully pulled ${chalk.bold(total)} teams.`);
168
216
  }
169
217
 
170
218
  const pullMessagingTopic = async () => {
171
- const { topics } = await paginate(messagingListTopics, { parseOutput: false }, 100, 'topics');
219
+ log("Fetching topics ...");
220
+ let total = 0;
221
+
222
+ const fetchResponse = await messagingListTopics({
223
+ queries: [JSON.stringify({ method: 'limit', values: [1] })],
224
+ parseOutput: false
225
+ });
226
+ if (fetchResponse["topics"].length <= 0) {
227
+ log("No topics found.");
228
+ success(`Successfully pulled ${chalk.bold(total)} topics.`);
229
+ return;
230
+ }
172
231
 
173
- log(`Found ${topics.length} topics`);
232
+ const { topics } = await paginate(messagingListTopics, { parseOutput: false }, 100, 'topics');
174
233
 
175
- topics.forEach(topic => {
234
+ for(const topic of topics) {
235
+ total++;
236
+ log(`Pulling topic ${chalk.bold(topic['name'])} ...`);
176
237
  localConfig.addMessagingTopic(topic);
177
- });
238
+ }
178
239
 
179
- success();
240
+ success(`Successfully pulled ${chalk.bold(total)} topics.`);
180
241
  }
181
242
 
182
243
  const pull = new Command("pull")
@@ -192,9 +253,9 @@ pull
192
253
  }));
193
254
 
194
255
  pull
195
- .command("project")
256
+ .command("settings")
196
257
  .description("Pull your Appwrite project name, services and auth settings")
197
- .action(actionRunner(pullProject));
258
+ .action(actionRunner(pullSettings));
198
259
 
199
260
  pull
200
261
  .command("function")
@@ -228,4 +289,5 @@ pull
228
289
 
229
290
  module.exports = {
230
291
  pull,
292
+ pullResources
231
293
  };