Skip to content

Commit 9b01187

Browse files
committed
Merge remote-tracking branch 'origin/master' into fix-cli-docker-image-pulling
2 parents ffbfe24 + c3c060a commit 9b01187

File tree

9 files changed

+152
-110
lines changed

9 files changed

+152
-110
lines changed

templates/cli/lib/client.js.twig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class Client {
118118

119119
body = formData;
120120
} else {
121-
body = JSON.stringify(params);
121+
body = JSONbig.stringify(params);
122122
}
123123

124124
let response = undefined;
@@ -174,7 +174,7 @@ class Client {
174174
const text = await response.text();
175175
let json = undefined;
176176
try {
177-
json = JSON.parse(text);
177+
json = JSONbig.parse(text);
178178
} catch (error) {
179179
return text;
180180
}

templates/cli/lib/commands/pull.js.twig

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const { databasesGet, databasesListCollections, databasesList } = require("./dat
1111
const { storageListBuckets } = require("./storage");
1212
const { localConfig } = require("../config");
1313
const { paginate } = require("../paginate");
14-
const { questionsPullCollection, questionsPullFunctions, questionsPullResources } = require("../questions");
14+
const { questionsPullCollection, questionsPullFunctions, questionsPullFunctionsCode, questionsPullResources } = require("../questions");
1515
const { cliConfig, success, log, warn, actionRunner, commandDescriptions } = require("../parser");
1616

1717
const pullResources = async () => {
@@ -56,7 +56,7 @@ const pullSettings = async () => {
5656
}
5757
}
5858

59-
const pullFunctions = async () => {
59+
const pullFunctions = async ({ code }) => {
6060
log("Fetching functions ...");
6161
let total = 0;
6262

@@ -74,11 +74,15 @@ const pullFunctions = async () => {
7474
? (await paginate(functionsList, { parseOutput: false }, 100, 'functions')).functions
7575
: (await inquirer.prompt(questionsPullFunctions)).functions;
7676

77+
let allowCodePull = cliConfig.force === true ? true : null;
78+
7779
for (let func of functions) {
7880
total++;
7981
log(`Pulling function ${chalk.bold(func['name'])} ...`);
8082

8183
const localFunction = localConfig.getFunction(func.$id);
84+
85+
func['path'] = localFunction['path'];
8286
if(!localFunction['path']) {
8387
func['path'] = `functions/${func.$id}`;
8488
}
@@ -88,28 +92,40 @@ const pullFunctions = async () => {
8892
if (!fs.existsSync(func['path'])) {
8993
fs.mkdirSync(func['path'], { recursive: true });
9094
}
91-
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-
});
101-
102-
tar.extract({
103-
sync: true,
104-
cwd: func['path'],
105-
file: compressedFileName,
106-
strict: false,
107-
});
108-
109-
fs.rmSync(compressedFileName);
110-
}
111-
}
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+
});
112117

118+
tar.extract({
119+
sync: true,
120+
cwd: func['path'],
121+
file: compressedFileName,
122+
strict: false,
123+
});
124+
125+
fs.rmSync(compressedFileName);
126+
}
127+
}
128+
113129
success(`Successfully pulled ${chalk.bold(total)} functions.`);
114130
}
115131

@@ -261,6 +277,7 @@ pull
261277
.command("function")
262278
.alias("functions")
263279
.description("Pulling your {{ spec.title|caseUcfirst }} cloud function")
280+
.option("--no-code", "Don't pull the function's code")
264281
.action(actionRunner(pullFunctions))
265282

266283
pull

templates/cli/lib/commands/push.js.twig

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ const { checkDeployConditions } = require('../utils');
6767

6868
const STEP_SIZE = 100; // Resources
6969
const POLL_DEBOUNCE = 2000; // Milliseconds
70-
const POLL_MAX_DEBOUNCE = 30; // Times
70+
const POLL_MAX_DEBOUNCE = 1800; // Times of POLL_DEBOUNCE (1 hour)
7171

7272
let pollMaxDebounces = 30;
7373

@@ -354,8 +354,8 @@ const createAttribute = async (databaseId, collectionId, attribute) => {
354354
collectionId,
355355
key: attribute.key,
356356
required: attribute.required,
357-
min: parseInt(attribute.min.toString()),
358-
max: parseInt(attribute.max.toString()),
357+
min: attribute.min,
358+
max: attribute.max,
359359
xdefault: attribute.default,
360360
array: attribute.array,
361361
parseOutput: false
@@ -366,8 +366,8 @@ const createAttribute = async (databaseId, collectionId, attribute) => {
366366
collectionId,
367367
key: attribute.key,
368368
required: attribute.required,
369-
min: parseFloat(attribute.min.toString()),
370-
max: parseFloat(attribute.max.toString()),
369+
min: attribute.min,
370+
max: attribute.max,
371371
xdefault: attribute.default,
372372
array: attribute.array,
373373
parseOutput: false
@@ -471,8 +471,8 @@ const updateAttribute = async (databaseId, collectionId, attribute) => {
471471
collectionId,
472472
key: attribute.key,
473473
required: attribute.required,
474-
min: parseInt(attribute.min.toString()),
475-
max: parseInt(attribute.max.toString()),
474+
min: attribute.min,
475+
max: attribute.max,
476476
xdefault: attribute.default,
477477
array: attribute.array,
478478
parseOutput: false
@@ -483,8 +483,8 @@ const updateAttribute = async (databaseId, collectionId, attribute) => {
483483
collectionId,
484484
key: attribute.key,
485485
required: attribute.required,
486-
min: parseFloat(attribute.min.toString()),
487-
max: parseFloat(attribute.max.toString()),
486+
min: attribute.min,
487+
max: attribute.max,
488488
xdefault: attribute.default,
489489
array: attribute.array,
490490
parseOutput: false
@@ -884,6 +884,7 @@ const pushFunction = async ({ functionId, async, returnOnZero } = { returnOnZero
884884
logging: func.logging,
885885
entrypoint: func.entrypoint,
886886
commands: func.commands,
887+
scopes: func.scopes,
887888
providerRepositoryId: func.providerRepositoryId ?? "",
888889
installationId: func.installationId ?? '',
889890
providerBranch: func.providerBranch ?? '',

templates/cli/lib/commands/run.js.twig

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,12 @@ const runFunction = async ({ port, functionId, noVariables, noReload, userId } =
8686
log("If you wish to change your local settings, update the appwrite.json file and rerun the 'appwrite run' command.");
8787
hint("Permissions, events, CRON and timeouts dont apply when running locally.");
8888

89-
await dockerCleanup();
89+
await dockerCleanup(func.$id);
9090

9191
process.on('SIGINT', async () => {
9292
log('Cleaning up ...');
93-
await dockerCleanup();
94-
success();
93+
await dockerCleanup(func.$id);
94+
success("Local function successfully stopped.");
9595
process.exit();
9696
});
9797

@@ -135,7 +135,7 @@ const runFunction = async ({ port, functionId, noVariables, noReload, userId } =
135135
variables['APPWRITE_FUNCTION_RUNTIME_VERSION'] = func.runtime;
136136

137137
try {
138-
await JwtManager.setup(userId);
138+
await JwtManager.setup(userId, func.scopes ?? []);
139139
} catch(err) {
140140
warn("Dynamic API key not generated. Header x-appwrite-key will not be set. Reason: " + err.message);
141141
}
@@ -150,14 +150,6 @@ const runFunction = async ({ port, functionId, noVariables, noReload, userId } =
150150

151151
await dockerPull(func);
152152

153-
log('Building function using Docker ...');
154-
await dockerBuild(func, variables);
155-
156-
log('Starting function using Docker ...');
157-
hint('Function automatically restarts when you edit your code.');
158-
159-
await dockerStart(func, variables, port);
160-
161153
new Tail(logsPath).on("line", function(data) {
162154
process.stdout.write(chalk.white(`${data}\n`));
163155
});
@@ -183,8 +175,14 @@ const runFunction = async ({ port, functionId, noVariables, noReload, userId } =
183175

184176
const dependencyFile = files.find((filePath) => tool.dependencyFiles.includes(filePath));
185177
if(tool.isCompiled || dependencyFile) {
186-
log(`Rebuilding the function ...`);
178+
log(`Rebuilding the function due to file changes ...`);
187179
await dockerBuild(func, variables);
180+
181+
if(!Queue.isEmpty()) {
182+
Queue.unlock();
183+
return;
184+
}
185+
188186
await dockerStart(func, variables, port);
189187
} else {
190188
log('Hot-swapping function.. Files with change are ' + files.join(', '));
@@ -249,6 +247,22 @@ const runFunction = async ({ port, functionId, noVariables, noReload, userId } =
249247
Queue.unlock();
250248
}
251249
});
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();
252266
}
253267

254268
const run = new Command("run")

templates/cli/lib/config.js.twig

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,36 @@ const _path = require("path");
44
const process = require("process");
55
const JSONbig = require("json-bigint")({ storeAsString: false });
66

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 = ["key", "type", "required", "array", "size", "default"];
13-
const KeyIndexes = ["key", "type", "status", "attributes", "orders"];
14-
15-
function whitelistKeys(value, keys, nestedKeys = []) {
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 = {}) {
1637
if(Array.isArray(value)) {
1738
const newValue = [];
1839

@@ -25,7 +46,7 @@ function whitelistKeys(value, keys, nestedKeys = []) {
2546

2647
const newValue = {};
2748
Object.keys(value).forEach((key) => {
28-
if(keys.includes(key)) {
49+
if(keys.has(key)) {
2950
if(nestedKeys[key]) {
3051
newValue[key] = whitelistKeys(value[key], nestedKeys[key]);
3152
} else {

0 commit comments

Comments
 (0)