appwrite-cli 6.0.0-rc.2 → 6.0.0-rc.4
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 +2 -2
- package/docs/examples/account/delete-mfa-authenticator.md +1 -2
- package/install.ps1 +2 -2
- package/install.sh +1 -1
- package/lib/client.js +4 -4
- package/lib/commands/account.js +1 -6
- package/lib/commands/pull.js +40 -22
- package/lib/commands/push.js +10 -9
- package/lib/commands/run.js +29 -13
- package/lib/config.js +31 -10
- package/lib/emulation/docker.js +59 -79
- package/lib/emulation/utils.js +7 -3
- package/lib/parser.js +1 -1
- package/lib/questions.js +9 -0
- package/lib/sdks.js +1 -1
- package/package.json +1 -1
- package/scoop/appwrite.json +3 -3
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.
|
|
32
|
+
6.0.0-rc.4
|
|
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.
|
|
63
|
+
6.0.0-rc.4
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
## Getting Started
|
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.
|
|
17
|
-
$GITHUB_arm64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/6.0.0-rc.
|
|
16
|
+
$GITHUB_x64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/6.0.0-rc.4/appwrite-cli-win-x64.exe"
|
|
17
|
+
$GITHUB_arm64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/6.0.0-rc.4/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.
|
|
100
|
+
GITHUB_LATEST_VERSION="6.0.0-rc.4"
|
|
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.
|
|
20
|
-
'user-agent' : `AppwriteCLI/6.0.0-rc.
|
|
19
|
+
'x-sdk-version': '6.0.0-rc.4',
|
|
20
|
+
'user-agent' : `AppwriteCLI/6.0.0-rc.4 (${os.type()} ${os.version()}; ${os.arch()})`,
|
|
21
21
|
'X-Appwrite-Response-Format' : '1.5.0',
|
|
22
22
|
};
|
|
23
23
|
}
|
|
@@ -168,7 +168,7 @@ class Client {
|
|
|
168
168
|
|
|
169
169
|
body = formData;
|
|
170
170
|
} else {
|
|
171
|
-
body =
|
|
171
|
+
body = JSONbig.stringify(params);
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
let response = undefined;
|
|
@@ -224,7 +224,7 @@ class Client {
|
|
|
224
224
|
const text = await response.text();
|
|
225
225
|
let json = undefined;
|
|
226
226
|
try {
|
|
227
|
-
json =
|
|
227
|
+
json = JSONbig.parse(text);
|
|
228
228
|
} catch (error) {
|
|
229
229
|
return text;
|
|
230
230
|
}
|
package/lib/commands/account.js
CHANGED
|
@@ -430,7 +430,6 @@ const accountUpdateMfaAuthenticator = async ({type,otp,parseOutput = true, overr
|
|
|
430
430
|
/**
|
|
431
431
|
* @typedef {Object} AccountDeleteMfaAuthenticatorRequestParams
|
|
432
432
|
* @property {AuthenticatorType} type Type of authenticator.
|
|
433
|
-
* @property {string} otp Valid verification token.
|
|
434
433
|
* @property {boolean} overrideForCli
|
|
435
434
|
* @property {boolean} parseOutput
|
|
436
435
|
* @property {libClient | undefined} sdk
|
|
@@ -439,14 +438,11 @@ const accountUpdateMfaAuthenticator = async ({type,otp,parseOutput = true, overr
|
|
|
439
438
|
/**
|
|
440
439
|
* @param {AccountDeleteMfaAuthenticatorRequestParams} params
|
|
441
440
|
*/
|
|
442
|
-
const accountDeleteMfaAuthenticator = async ({type,
|
|
441
|
+
const accountDeleteMfaAuthenticator = async ({type,parseOutput = true, overrideForCli = false, sdk = undefined}) => {
|
|
443
442
|
let client = !sdk ? await sdkForProject() :
|
|
444
443
|
sdk;
|
|
445
444
|
let apiPath = '/account/mfa/authenticators/{type}'.replace('{type}', type);
|
|
446
445
|
let payload = {};
|
|
447
|
-
if (typeof otp !== 'undefined') {
|
|
448
|
-
payload['otp'] = otp;
|
|
449
|
-
}
|
|
450
446
|
|
|
451
447
|
let response = undefined;
|
|
452
448
|
|
|
@@ -1847,7 +1843,6 @@ account
|
|
|
1847
1843
|
.command(`deleteMfaAuthenticator`)
|
|
1848
1844
|
.description(`Delete an authenticator for a user by ID.`)
|
|
1849
1845
|
.requiredOption(`--type <type>`, `Type of authenticator.`)
|
|
1850
|
-
.requiredOption(`--otp <otp>`, `Valid verification token.`)
|
|
1851
1846
|
.action(actionRunner(accountDeleteMfaAuthenticator))
|
|
1852
1847
|
|
|
1853
1848
|
account
|
package/lib/commands/pull.js
CHANGED
|
@@ -11,7 +11,7 @@ const { databasesGet, databasesListCollections, databasesList } = require("./dat
|
|
|
11
11
|
const { storageListBuckets } = require("./storage");
|
|
12
12
|
const { localConfig } = require("../config");
|
|
13
13
|
const { paginate } = require("../paginate");
|
|
14
|
-
const { questionsPullCollection, questionsPullFunctions, questionsPullResources } = require("../questions");
|
|
14
|
+
const { questionsPullCollection, questionsPullFunctions, questionsPullFunctionsCode, questionsPullResources } = require("../questions");
|
|
15
15
|
const { cliConfig, success, log, warn, actionRunner, commandDescriptions } = require("../parser");
|
|
16
16
|
|
|
17
17
|
const pullResources = async () => {
|
|
@@ -56,7 +56,7 @@ const pullSettings = async () => {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
const pullFunctions = async () => {
|
|
59
|
+
const pullFunctions = async ({ code }) => {
|
|
60
60
|
log("Fetching functions ...");
|
|
61
61
|
let total = 0;
|
|
62
62
|
|
|
@@ -74,11 +74,15 @@ const pullFunctions = async () => {
|
|
|
74
74
|
? (await paginate(functionsList, { parseOutput: false }, 100, 'functions')).functions
|
|
75
75
|
: (await inquirer.prompt(questionsPullFunctions)).functions;
|
|
76
76
|
|
|
77
|
+
let allowCodePull = cliConfig.force === true ? true : null;
|
|
78
|
+
|
|
77
79
|
for (let func of functions) {
|
|
78
80
|
total++;
|
|
79
81
|
log(`Pulling function ${chalk.bold(func['name'])} ...`);
|
|
80
82
|
|
|
81
83
|
const localFunction = localConfig.getFunction(func.$id);
|
|
84
|
+
|
|
85
|
+
func['path'] = localFunction['path'];
|
|
82
86
|
if(!localFunction['path']) {
|
|
83
87
|
func['path'] = `functions/${func.$id}`;
|
|
84
88
|
}
|
|
@@ -88,28 +92,41 @@ const pullFunctions = async () => {
|
|
|
88
92
|
if (!fs.existsSync(func['path'])) {
|
|
89
93
|
fs.mkdirSync(func['path'], { recursive: true });
|
|
90
94
|
}
|
|
91
|
-
|
|
92
|
-
if(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
95
|
+
|
|
96
|
+
if(code === false) {
|
|
97
|
+
warn("Source code download skipped.");
|
|
98
|
+
} else if(!func['deployment']) {
|
|
99
|
+
warn("Source code download skipped because function doesn't have active deployment.");
|
|
100
|
+
} else {
|
|
101
|
+
if(allowCodePull === null) {
|
|
102
|
+
const codeAnswer = await inquirer.prompt(questionsPullFunctionsCode);
|
|
103
|
+
allowCodePull = codeAnswer.override;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if(allowCodePull) {
|
|
107
|
+
log("Pulling active deployment's code ...");
|
|
108
|
+
|
|
109
|
+
const compressedFileName = `${func['$id']}-${+new Date()}.tar.gz`
|
|
110
|
+
await functionsDownloadDeployment({
|
|
111
|
+
functionId: func['$id'],
|
|
112
|
+
deploymentId: func['deployment'],
|
|
113
|
+
destination: compressedFileName,
|
|
114
|
+
overrideForCli: true,
|
|
115
|
+
parseOutput: false
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
tar.extract({
|
|
119
|
+
sync: true,
|
|
120
|
+
cwd: func['path'],
|
|
121
|
+
file: compressedFileName,
|
|
122
|
+
strict: false,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
fs.rmSync(compressedFileName);
|
|
126
|
+
}
|
|
110
127
|
}
|
|
111
128
|
}
|
|
112
|
-
|
|
129
|
+
|
|
113
130
|
success(`Successfully pulled ${chalk.bold(total)} functions.`);
|
|
114
131
|
}
|
|
115
132
|
|
|
@@ -261,6 +278,7 @@ pull
|
|
|
261
278
|
.command("function")
|
|
262
279
|
.alias("functions")
|
|
263
280
|
.description("Pulling your Appwrite cloud function")
|
|
281
|
+
.option("--no-code", "Don't pull the function's code")
|
|
264
282
|
.action(actionRunner(pullFunctions))
|
|
265
283
|
|
|
266
284
|
pull
|
package/lib/commands/push.js
CHANGED
|
@@ -67,7 +67,7 @@ const { checkDeployConditions } = require('../utils');
|
|
|
67
67
|
|
|
68
68
|
const STEP_SIZE = 100; // Resources
|
|
69
69
|
const POLL_DEBOUNCE = 2000; // Milliseconds
|
|
70
|
-
const POLL_MAX_DEBOUNCE =
|
|
70
|
+
const POLL_MAX_DEBOUNCE = 1800; // Times of POLL_DEBOUNCE (1 hour)
|
|
71
71
|
|
|
72
72
|
let pollMaxDebounces = 30;
|
|
73
73
|
|
|
@@ -354,8 +354,8 @@ const createAttribute = async (databaseId, collectionId, attribute) => {
|
|
|
354
354
|
collectionId,
|
|
355
355
|
key: attribute.key,
|
|
356
356
|
required: attribute.required,
|
|
357
|
-
min:
|
|
358
|
-
max:
|
|
357
|
+
min: attribute.min,
|
|
358
|
+
max: attribute.max,
|
|
359
359
|
xdefault: attribute.default,
|
|
360
360
|
array: attribute.array,
|
|
361
361
|
parseOutput: false
|
|
@@ -366,8 +366,8 @@ const createAttribute = async (databaseId, collectionId, attribute) => {
|
|
|
366
366
|
collectionId,
|
|
367
367
|
key: attribute.key,
|
|
368
368
|
required: attribute.required,
|
|
369
|
-
min:
|
|
370
|
-
max:
|
|
369
|
+
min: attribute.min,
|
|
370
|
+
max: attribute.max,
|
|
371
371
|
xdefault: attribute.default,
|
|
372
372
|
array: attribute.array,
|
|
373
373
|
parseOutput: false
|
|
@@ -471,8 +471,8 @@ const updateAttribute = async (databaseId, collectionId, attribute) => {
|
|
|
471
471
|
collectionId,
|
|
472
472
|
key: attribute.key,
|
|
473
473
|
required: attribute.required,
|
|
474
|
-
min:
|
|
475
|
-
max:
|
|
474
|
+
min: attribute.min,
|
|
475
|
+
max: attribute.max,
|
|
476
476
|
xdefault: attribute.default,
|
|
477
477
|
array: attribute.array,
|
|
478
478
|
parseOutput: false
|
|
@@ -483,8 +483,8 @@ const updateAttribute = async (databaseId, collectionId, attribute) => {
|
|
|
483
483
|
collectionId,
|
|
484
484
|
key: attribute.key,
|
|
485
485
|
required: attribute.required,
|
|
486
|
-
min:
|
|
487
|
-
max:
|
|
486
|
+
min: attribute.min,
|
|
487
|
+
max: attribute.max,
|
|
488
488
|
xdefault: attribute.default,
|
|
489
489
|
array: attribute.array,
|
|
490
490
|
parseOutput: false
|
|
@@ -884,6 +884,7 @@ const pushFunction = async ({ functionId, async, returnOnZero } = { returnOnZero
|
|
|
884
884
|
logging: func.logging,
|
|
885
885
|
entrypoint: func.entrypoint,
|
|
886
886
|
commands: func.commands,
|
|
887
|
+
scopes: func.scopes,
|
|
887
888
|
providerRepositoryId: func.providerRepositoryId ?? "",
|
|
888
889
|
installationId: func.installationId ?? '',
|
|
889
890
|
providerBranch: func.providerBranch ?? '',
|
package/lib/commands/run.js
CHANGED
|
@@ -86,12 +86,12 @@ const runFunction = async ({ port, functionId, noVariables, noReload, userId } =
|
|
|
86
86
|
log("If you wish to change your local settings, update the appwrite.json file and rerun the 'appwrite run' command.");
|
|
87
87
|
hint("Permissions, events, CRON and timeouts dont apply when running locally.");
|
|
88
88
|
|
|
89
|
-
await dockerCleanup();
|
|
89
|
+
await dockerCleanup(func.$id);
|
|
90
90
|
|
|
91
91
|
process.on('SIGINT', async () => {
|
|
92
92
|
log('Cleaning up ...');
|
|
93
|
-
await dockerCleanup();
|
|
94
|
-
success();
|
|
93
|
+
await dockerCleanup(func.$id);
|
|
94
|
+
success("Local function successfully stopped.");
|
|
95
95
|
process.exit();
|
|
96
96
|
});
|
|
97
97
|
|
|
@@ -135,7 +135,7 @@ const runFunction = async ({ port, functionId, noVariables, noReload, userId } =
|
|
|
135
135
|
variables['APPWRITE_FUNCTION_RUNTIME_VERSION'] = func.runtime;
|
|
136
136
|
|
|
137
137
|
try {
|
|
138
|
-
await JwtManager.setup(userId);
|
|
138
|
+
await JwtManager.setup(userId, func.scopes ?? []);
|
|
139
139
|
} catch(err) {
|
|
140
140
|
warn("Dynamic API key not generated. Header x-appwrite-key will not be set. Reason: " + err.message);
|
|
141
141
|
}
|
|
@@ -149,18 +149,12 @@ const runFunction = async ({ port, functionId, noVariables, noReload, userId } =
|
|
|
149
149
|
variables['OPEN_RUNTIMES_HEADERS'] = JSON.stringify(headers);
|
|
150
150
|
|
|
151
151
|
await dockerPull(func);
|
|
152
|
-
await dockerBuild(func, variables);
|
|
153
|
-
|
|
154
|
-
log('Starting function using Docker ...');
|
|
155
|
-
hint('Function automatically restarts when you edit your code.');
|
|
156
|
-
|
|
157
|
-
await dockerStart(func, variables, port);
|
|
158
152
|
|
|
159
153
|
new Tail(logsPath).on("line", function(data) {
|
|
160
|
-
process.stdout.write(chalk.
|
|
154
|
+
process.stdout.write(chalk.white(`${data}\n`));
|
|
161
155
|
});
|
|
162
156
|
new Tail(errorsPath).on("line", function(data) {
|
|
163
|
-
process.stdout.write(chalk.
|
|
157
|
+
process.stdout.write(chalk.white(`${data}\n`));
|
|
164
158
|
});
|
|
165
159
|
|
|
166
160
|
if(!noReload) {
|
|
@@ -181,8 +175,14 @@ const runFunction = async ({ port, functionId, noVariables, noReload, userId } =
|
|
|
181
175
|
|
|
182
176
|
const dependencyFile = files.find((filePath) => tool.dependencyFiles.includes(filePath));
|
|
183
177
|
if(tool.isCompiled || dependencyFile) {
|
|
184
|
-
log(`Rebuilding the function ...`);
|
|
178
|
+
log(`Rebuilding the function due to file changes ...`);
|
|
185
179
|
await dockerBuild(func, variables);
|
|
180
|
+
|
|
181
|
+
if(!Queue.isEmpty()) {
|
|
182
|
+
Queue.unlock();
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
186
|
await dockerStart(func, variables, port);
|
|
187
187
|
} else {
|
|
188
188
|
log('Hot-swapping function.. Files with change are ' + files.join(', '));
|
|
@@ -247,6 +247,22 @@ const runFunction = async ({ port, functionId, noVariables, noReload, userId } =
|
|
|
247
247
|
Queue.unlock();
|
|
248
248
|
}
|
|
249
249
|
});
|
|
250
|
+
|
|
251
|
+
Queue.lock();
|
|
252
|
+
|
|
253
|
+
log('Building function using Docker ...');
|
|
254
|
+
await dockerBuild(func, variables);
|
|
255
|
+
|
|
256
|
+
if(!Queue.isEmpty()) {
|
|
257
|
+
Queue.unlock();
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
log('Starting function using Docker ...');
|
|
262
|
+
hint('Function automatically restarts when you edit your code.');
|
|
263
|
+
await dockerStart(func, variables, port);
|
|
264
|
+
|
|
265
|
+
Queue.unlock();
|
|
250
266
|
}
|
|
251
267
|
|
|
252
268
|
const run = new Command("run")
|
package/lib/config.js
CHANGED
|
@@ -4,15 +4,36 @@ const _path = require("path");
|
|
|
4
4
|
const process = require("process");
|
|
5
5
|
const JSONbig = require("json-bigint")({ storeAsString: false });
|
|
6
6
|
|
|
7
|
-
const KeysFunction = ["path", "$id", "execute", "name", "enabled", "logging", "runtime", "scopes", "events", "schedule", "timeout", "entrypoint", "commands"];
|
|
8
|
-
const KeysDatabase = ["$id", "name", "enabled"];
|
|
9
|
-
const KeysCollection = ["$id", "$permissions", "databaseId", "name", "enabled", "documentSecurity", "attributes", "indexes"];
|
|
10
|
-
const KeysStorage = ["$id", "$permissions", "fileSecurity", "name", "enabled", "maximumFileSize", "allowedFileExtensions", "compression", "encryption", "antivirus"];
|
|
11
|
-
const KeyTopics = ["$id", "name", "subscribe"];
|
|
12
|
-
const KeyAttributes = [
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
const KeysFunction = new Set(["path", "$id", "execute", "name", "enabled", "logging", "runtime", "scopes", "events", "schedule", "timeout", "entrypoint", "commands"]);
|
|
8
|
+
const KeysDatabase = new Set(["$id", "name", "enabled"]);
|
|
9
|
+
const KeysCollection = new Set(["$id", "$permissions", "databaseId", "name", "enabled", "documentSecurity", "attributes", "indexes"]);
|
|
10
|
+
const KeysStorage = new Set(["$id", "$permissions", "fileSecurity", "name", "enabled", "maximumFileSize", "allowedFileExtensions", "compression", "encryption", "antivirus"]);
|
|
11
|
+
const KeyTopics = new Set(["$id", "name", "subscribe"]);
|
|
12
|
+
const KeyAttributes = new Set([
|
|
13
|
+
"key",
|
|
14
|
+
"type",
|
|
15
|
+
"required",
|
|
16
|
+
"array",
|
|
17
|
+
"size",
|
|
18
|
+
"default",
|
|
19
|
+
// integer and float
|
|
20
|
+
"min",
|
|
21
|
+
"max",
|
|
22
|
+
// email, enum, URL, IP, and datetime
|
|
23
|
+
"format",
|
|
24
|
+
// enum
|
|
25
|
+
"elements",
|
|
26
|
+
// relationship
|
|
27
|
+
"relatedCollection",
|
|
28
|
+
"relationType",
|
|
29
|
+
"twoWay",
|
|
30
|
+
"twoWayKey",
|
|
31
|
+
"onDelete",
|
|
32
|
+
"side"
|
|
33
|
+
]);
|
|
34
|
+
const KeyIndexes = new Set(["key", "type", "status", "attributes", "orders"]);
|
|
35
|
+
|
|
36
|
+
function whitelistKeys(value, keys, nestedKeys = {}) {
|
|
16
37
|
if(Array.isArray(value)) {
|
|
17
38
|
const newValue = [];
|
|
18
39
|
|
|
@@ -25,7 +46,7 @@ function whitelistKeys(value, keys, nestedKeys = []) {
|
|
|
25
46
|
|
|
26
47
|
const newValue = {};
|
|
27
48
|
Object.keys(value).forEach((key) => {
|
|
28
|
-
if(keys.
|
|
49
|
+
if(keys.has(key)) {
|
|
29
50
|
if(nestedKeys[key]) {
|
|
30
51
|
newValue[key] = whitelistKeys(value[key], nestedKeys[key]);
|
|
31
52
|
} else {
|
package/lib/emulation/docker.js
CHANGED
|
@@ -4,11 +4,15 @@ const { localConfig } = require("../config");
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const { log, success, hint } = require("../parser");
|
|
7
|
-
const { openRuntimesVersion, systemTools } = require("./utils");
|
|
7
|
+
const { openRuntimesVersion, systemTools, Queue } = require("./utils");
|
|
8
8
|
|
|
9
9
|
async function dockerStop(id) {
|
|
10
10
|
const stopProcess = childProcess.spawn('docker', ['rm', '--force', id], {
|
|
11
11
|
stdio: 'pipe',
|
|
12
|
+
env: {
|
|
13
|
+
...process.env,
|
|
14
|
+
DOCKER_CLI_HINTS: 'false'
|
|
15
|
+
}
|
|
12
16
|
});
|
|
13
17
|
|
|
14
18
|
await new Promise((res) => { stopProcess.on('close', res) });
|
|
@@ -20,45 +24,20 @@ async function dockerPull(func) {
|
|
|
20
24
|
const runtimeName = runtimeChunks.join("-");
|
|
21
25
|
const imageName = `openruntimes/${runtimeName}:${openRuntimesVersion}-${runtimeVersion}`;
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
stdio: 'pipe',
|
|
25
|
-
pwd: path.join(process.cwd(), func.path)
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
let hasImage = false;
|
|
29
|
-
|
|
30
|
-
checkProcess.stdout.on('data', (data) => {
|
|
31
|
-
if(data) {
|
|
32
|
-
hasImage = false;
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
checkProcess.stderr.on('data', (data) => {
|
|
37
|
-
if(data) {
|
|
38
|
-
hasImage = false;
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
await new Promise((res) => { checkProcess.on('close', res) });
|
|
43
|
-
|
|
44
|
-
if(hasImage) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
log('Pulling Docker image ...');
|
|
49
|
-
hint('This may take a few minutes, but we only need to do this once.');
|
|
27
|
+
log('Verifying Docker image ...');
|
|
50
28
|
|
|
51
29
|
const pullProcess = childProcess.spawn('docker', ['pull', imageName], {
|
|
52
30
|
stdio: 'pipe',
|
|
53
|
-
|
|
31
|
+
env: {
|
|
32
|
+
...process.env,
|
|
33
|
+
DOCKER_CLI_HINTS: 'false'
|
|
34
|
+
}
|
|
54
35
|
});
|
|
55
36
|
|
|
56
37
|
await new Promise((res) => { pullProcess.on('close', res) });
|
|
57
38
|
}
|
|
58
39
|
|
|
59
40
|
async function dockerBuild(func, variables) {
|
|
60
|
-
log('Building function using Docker ...');
|
|
61
|
-
|
|
62
41
|
const runtimeChunks = func.runtime.split("-");
|
|
63
42
|
const runtimeVersion = runtimeChunks.pop();
|
|
64
43
|
const runtimeName = runtimeChunks.join("-");
|
|
@@ -74,7 +53,6 @@ async function dockerBuild(func, variables) {
|
|
|
74
53
|
params.push('-e', 'APPWRITE_ENV=development');
|
|
75
54
|
params.push('-e', 'OPEN_RUNTIMES_ENV=development');
|
|
76
55
|
params.push('-e', 'OPEN_RUNTIMES_SECRET=');
|
|
77
|
-
params.push('-l', 'appwrite-env=dev');
|
|
78
56
|
params.push('-e', `OPEN_RUNTIMES_ENTRYPOINT=${func.entrypoint}`);
|
|
79
57
|
|
|
80
58
|
for(const k of Object.keys(variables)) {
|
|
@@ -85,7 +63,11 @@ async function dockerBuild(func, variables) {
|
|
|
85
63
|
|
|
86
64
|
const buildProcess = childProcess.spawn('docker', params, {
|
|
87
65
|
stdio: 'pipe',
|
|
88
|
-
pwd: functionDir
|
|
66
|
+
pwd: functionDir,
|
|
67
|
+
env: {
|
|
68
|
+
...process.env,
|
|
69
|
+
DOCKER_CLI_HINTS: 'false'
|
|
70
|
+
}
|
|
89
71
|
});
|
|
90
72
|
|
|
91
73
|
buildProcess.stdout.on('data', (data) => {
|
|
@@ -96,8 +78,25 @@ async function dockerBuild(func, variables) {
|
|
|
96
78
|
process.stderr.write(chalk.blackBright(`${data}\n`));
|
|
97
79
|
});
|
|
98
80
|
|
|
81
|
+
const killInterval = setInterval(() => {
|
|
82
|
+
if(!Queue.isEmpty()) {
|
|
83
|
+
log('Cancelling build ...');
|
|
84
|
+
buildProcess.stdout.destroy();
|
|
85
|
+
buildProcess.stdin.destroy();
|
|
86
|
+
buildProcess.stderr.destroy();
|
|
87
|
+
buildProcess.kill("SIGKILL");
|
|
88
|
+
clearInterval(killInterval);
|
|
89
|
+
}
|
|
90
|
+
}, 100);
|
|
91
|
+
|
|
99
92
|
await new Promise((res) => { buildProcess.on('close', res) });
|
|
100
93
|
|
|
94
|
+
clearInterval(interval);
|
|
95
|
+
|
|
96
|
+
if(!Queue.isEmpty()) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
101
100
|
const copyPath = path.join(process.cwd(), func.path, '.appwrite', 'build.tar.gz');
|
|
102
101
|
const copyDir = path.dirname(copyPath);
|
|
103
102
|
if (!fs.existsSync(copyDir)) {
|
|
@@ -106,7 +105,11 @@ async function dockerBuild(func, variables) {
|
|
|
106
105
|
|
|
107
106
|
const copyProcess = childProcess.spawn('docker', ['cp', `${id}:/mnt/code/code.tar.gz`, copyPath], {
|
|
108
107
|
stdio: 'pipe',
|
|
109
|
-
pwd: functionDir
|
|
108
|
+
pwd: functionDir,
|
|
109
|
+
env: {
|
|
110
|
+
...process.env,
|
|
111
|
+
DOCKER_CLI_HINTS: 'false'
|
|
112
|
+
}
|
|
110
113
|
});
|
|
111
114
|
|
|
112
115
|
await new Promise((res) => { copyProcess.on('close', res) });
|
|
@@ -133,10 +136,8 @@ async function dockerStart(func, variables, port) {
|
|
|
133
136
|
|
|
134
137
|
const params = [ 'run' ];
|
|
135
138
|
params.push('--rm');
|
|
136
|
-
params.push('-d');
|
|
137
139
|
params.push('--name', id);
|
|
138
140
|
params.push('-p', `${port}:3000`);
|
|
139
|
-
params.push('-l', 'appwrite-env=dev');
|
|
140
141
|
params.push('-e', 'APPWRITE_ENV=development');
|
|
141
142
|
params.push('-e', 'OPEN_RUNTIMES_ENV=development');
|
|
142
143
|
params.push('-e', 'OPEN_RUNTIMES_SECRET=');
|
|
@@ -150,58 +151,38 @@ async function dockerStart(func, variables, port) {
|
|
|
150
151
|
params.push('-v', `${functionDir}/.appwrite/build.tar.gz:/mnt/code/code.tar.gz:ro`);
|
|
151
152
|
params.push(imageName, 'sh', '-c', `helpers/start.sh "${tool.startCommand}"`);
|
|
152
153
|
|
|
153
|
-
childProcess.spawn('docker', params, {
|
|
154
|
+
const startProcess = childProcess.spawn('docker', params, {
|
|
154
155
|
stdio: 'pipe',
|
|
155
|
-
pwd: functionDir
|
|
156
|
+
pwd: functionDir,
|
|
157
|
+
env: {
|
|
158
|
+
...process.env,
|
|
159
|
+
DOCKER_CLI_HINTS: 'false'
|
|
160
|
+
}
|
|
156
161
|
});
|
|
157
162
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
async function dockerCleanup() {
|
|
162
|
-
await dockerStopActive();
|
|
163
|
+
startProcess.stdout.on('data', (data) => {
|
|
164
|
+
process.stdout.write(chalk.blackBright(data));
|
|
165
|
+
});
|
|
163
166
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if (fs.existsSync(appwritePath)) {
|
|
168
|
-
fs.rmSync(appwritePath, { recursive: true, force: true });
|
|
169
|
-
}
|
|
167
|
+
startProcess.stderr.on('data', (data) => {
|
|
168
|
+
process.stdout.write(chalk.blackBright(data));
|
|
169
|
+
});
|
|
170
170
|
|
|
171
|
-
|
|
172
|
-
if (fs.existsSync(tempPath)) {
|
|
173
|
-
fs.rmSync(tempPath, { force: true });
|
|
174
|
-
}
|
|
175
|
-
}
|
|
171
|
+
success(`Visit http://localhost:${port}/ to execute your function.`);
|
|
176
172
|
}
|
|
177
173
|
|
|
178
|
-
async function
|
|
179
|
-
|
|
180
|
-
stdio: 'pipe',
|
|
181
|
-
});
|
|
174
|
+
async function dockerCleanup(functionId) {
|
|
175
|
+
await dockerStop(functionId);
|
|
182
176
|
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if(id && !id.includes(' ')) {
|
|
188
|
-
ids.push(id);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
177
|
+
const func = localConfig.getFunction(functionId);
|
|
178
|
+
const appwritePath = path.join(process.cwd(), func.path, '.appwrite');
|
|
179
|
+
if (fs.existsSync(appwritePath)) {
|
|
180
|
+
fs.rmSync(appwritePath, { recursive: true, force: true });
|
|
191
181
|
}
|
|
192
182
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
listProcess.stderr.on('data', (data) => {
|
|
198
|
-
handleOutput(data);
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
await new Promise((res) => { listProcess.on('close', res) });
|
|
202
|
-
|
|
203
|
-
for(const id of ids) {
|
|
204
|
-
await dockerStop(id);
|
|
183
|
+
const tempPath = path.join(process.cwd(), func.path, 'code.tar.gz');
|
|
184
|
+
if (fs.existsSync(tempPath)) {
|
|
185
|
+
fs.rmSync(tempPath, { force: true });
|
|
205
186
|
}
|
|
206
187
|
}
|
|
207
188
|
|
|
@@ -210,6 +191,5 @@ module.exports = {
|
|
|
210
191
|
dockerBuild,
|
|
211
192
|
dockerStart,
|
|
212
193
|
dockerCleanup,
|
|
213
|
-
dockerStopActive,
|
|
214
194
|
dockerStop,
|
|
215
195
|
}
|
package/lib/emulation/utils.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const EventEmitter = require('node:events');
|
|
2
2
|
const { projectsCreateJWT } = require('../commands/projects');
|
|
3
3
|
const { localConfig } = require("../config");
|
|
4
|
+
const { usersGet, usersCreateJWT } = require("../commands/users");
|
|
5
|
+
const { log } = require("../parser");
|
|
4
6
|
|
|
5
7
|
const openRuntimesVersion = 'v4';
|
|
6
8
|
|
|
@@ -95,7 +97,7 @@ const JwtManager = {
|
|
|
95
97
|
timerWarn: null,
|
|
96
98
|
timerError: null,
|
|
97
99
|
|
|
98
|
-
async setup(userId = null) {
|
|
100
|
+
async setup(userId = null, projectScopes = []) {
|
|
99
101
|
if(this.timerWarn) {
|
|
100
102
|
clearTimeout(this.timerWarn);
|
|
101
103
|
}
|
|
@@ -128,8 +130,7 @@ const JwtManager = {
|
|
|
128
130
|
|
|
129
131
|
const functionResponse = await projectsCreateJWT({
|
|
130
132
|
projectId: localConfig.getProject().projectId,
|
|
131
|
-
|
|
132
|
-
scopes: ["sessions.write","users.read","users.write","teams.read","teams.write","databases.read","databases.write","collections.read","collections.write","attributes.read","attributes.write","indexes.read","indexes.write","documents.read","documents.write","files.read","files.write","buckets.read","buckets.write","functions.read","functions.write","execution.read","execution.write","locale.read","avatars.read","health.read","providers.read","providers.write","messages.read","messages.write","topics.read","topics.write","subscribers.read","subscribers.write","targets.read","targets.write","rules.read","rules.write","migrations.read","migrations.write","vcs.read","vcs.write","assistant.read"],
|
|
133
|
+
scopes: projectScopes,
|
|
133
134
|
duration: 60*60,
|
|
134
135
|
parseOutput: false
|
|
135
136
|
});
|
|
@@ -155,6 +156,9 @@ const Queue = {
|
|
|
155
156
|
this.files = [];
|
|
156
157
|
this.locked = true;
|
|
157
158
|
},
|
|
159
|
+
isEmpty() {
|
|
160
|
+
return this.files.length === 0
|
|
161
|
+
},
|
|
158
162
|
unlock() {
|
|
159
163
|
this.locked = false;
|
|
160
164
|
if(this.files.length > 0) {
|
package/lib/parser.js
CHANGED
|
@@ -131,7 +131,7 @@ const parseError = (err) => {
|
|
|
131
131
|
} catch {
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
const version = '6.0.0-rc.
|
|
134
|
+
const version = '6.0.0-rc.4';
|
|
135
135
|
const stepsToReproduce = `Running \`appwrite ${cliConfig.reportData.data.args.join(' ')}\``;
|
|
136
136
|
const yourEnvironment = `CLI version: ${version}\nOperation System: ${os.type()}\nAppwrite version: ${appwriteVersion}\nIs Cloud: ${isCloud}`;
|
|
137
137
|
|
package/lib/questions.js
CHANGED
|
@@ -258,6 +258,14 @@ const questionsPullFunctions = [
|
|
|
258
258
|
}
|
|
259
259
|
];
|
|
260
260
|
|
|
261
|
+
const questionsPullFunctionsCode = [
|
|
262
|
+
{
|
|
263
|
+
type: "confirm",
|
|
264
|
+
name: "override",
|
|
265
|
+
message: "Do you want to pull source code of active deployment?"
|
|
266
|
+
},
|
|
267
|
+
];
|
|
268
|
+
|
|
261
269
|
const questionsCreateFunction = [
|
|
262
270
|
{
|
|
263
271
|
type: "input",
|
|
@@ -841,6 +849,7 @@ module.exports = {
|
|
|
841
849
|
questionsCreateCollection,
|
|
842
850
|
questionsCreateMessagingTopic,
|
|
843
851
|
questionsPullFunctions,
|
|
852
|
+
questionsPullFunctionsCode,
|
|
844
853
|
questionsLogin,
|
|
845
854
|
questionsPullResources,
|
|
846
855
|
questionsLogout,
|
package/lib/sdks.js
CHANGED
|
@@ -30,7 +30,7 @@ const sdkForProject = async () => {
|
|
|
30
30
|
let selfSigned = globalConfig.getSelfSigned()
|
|
31
31
|
|
|
32
32
|
if (!project) {
|
|
33
|
-
throw new Error("Project is not set. Please run `appwrite init` to initialize the current directory with an Appwrite project.");
|
|
33
|
+
throw new Error("Project is not set. Please run `appwrite init project` to initialize the current directory with an Appwrite project.");
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
client
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "appwrite-cli",
|
|
3
3
|
"homepage": "https://appwrite.io/support",
|
|
4
4
|
"description": "Appwrite is an open-source self-hosted backend server that abstract and simplify complex and repetitive development tasks behind a very simple REST API",
|
|
5
|
-
"version": "6.0.0-rc.
|
|
5
|
+
"version": "6.0.0-rc.4",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"bin": {
|
package/scoop/appwrite.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/ScoopInstaller/Scoop/master/schema.json",
|
|
3
|
-
"version": "6.0.0-rc.
|
|
3
|
+
"version": "6.0.0-rc.4",
|
|
4
4
|
"description": "The Appwrite CLI is a command-line application that allows you to interact with Appwrite and perform server-side tasks using your terminal.",
|
|
5
5
|
"homepage": "https://github.com/appwrite/sdk-for-cli",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
7
7
|
"architecture": {
|
|
8
8
|
"64bit": {
|
|
9
|
-
"url": "https://github.com/appwrite/sdk-for-cli/releases/download/6.0.0-rc.
|
|
9
|
+
"url": "https://github.com/appwrite/sdk-for-cli/releases/download/6.0.0-rc.4/appwrite-cli-win-x64.exe",
|
|
10
10
|
"bin": [
|
|
11
11
|
[
|
|
12
12
|
"appwrite-cli-win-x64.exe",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
]
|
|
16
16
|
},
|
|
17
17
|
"arm64": {
|
|
18
|
-
"url": "https://github.com/appwrite/sdk-for-cli/releases/download/6.0.0-rc.
|
|
18
|
+
"url": "https://github.com/appwrite/sdk-for-cli/releases/download/6.0.0-rc.4/appwrite-cli-win-arm64.exe",
|
|
19
19
|
"bin": [
|
|
20
20
|
[
|
|
21
21
|
"appwrite-cli-win-arm64.exe",
|