1
+ const ignore = require("ignore");
2
+ const tar = require("tar");
3
+ const fs = require("fs");
1
4
const childProcess = require('child_process');
2
5
const chokidar = require('chokidar');
3
6
const inquirer = require("inquirer");
@@ -7,11 +10,12 @@ const { localConfig, globalConfig } = require("../config");
7
10
const { paginate } = require('../paginate');
8
11
const { questionsRunFunctions } = require("../questions");
9
12
const { actionRunner, success, log, error, commandDescriptions, drawTable } = require("../parser");
10
- const { systemHasCommand, isPortTaken } = require('../utils');
13
+ const { systemHasCommand, isPortTaken, getAllFiles } = require('../utils');
11
14
const { info } = require('console');
12
15
13
16
const activeDockerIds = {};
14
17
18
+ const openRuntimesVersion = 'v3';
15
19
const systemTools = {
16
20
'node': {
17
21
isCompiled: false,
@@ -35,10 +39,11 @@ async function dockerStop(id) {
35
39
}
36
40
37
41
async function dockerPull(func) {
42
+ return; // TODO: Remove
38
43
log('Pulling Docker image of function runtime ...');
39
44
40
45
const [ runtimeName, runtimeVersion ] = func.runtime.split('-', 2);
41
- const imageName = `openruntimes/${runtimeName}:v3 -${runtimeVersion}`;
46
+ const imageName = `openruntimes/${runtimeName}:${openRuntimesVersion} -${runtimeVersion}`;
42
47
43
48
const pullProcess = childProcess.spawn('docker', ['pull', imageName], {
44
49
stdio: 'pipe',
@@ -56,7 +61,7 @@ async function dockerBuild(func) {
56
61
log('Building function using Docker engine ...');
57
62
58
63
const [ runtimeName, runtimeVersion ] = func.runtime.split('-', 2);
59
- const imageName = `openruntimes/${runtimeName}:v3 -${runtimeVersion}`;
64
+ const imageName = `openruntimes/${runtimeName}:${openRuntimesVersion} -${runtimeVersion}`;
60
65
61
66
const functionDir = path.join(process.cwd(), func.path);
62
67
@@ -93,14 +98,14 @@ async function dockerStart(func, port) {
93
98
success(`Visit http://localhost:${port}/ to execute your function.`);
94
99
95
100
const [ runtimeName, runtimeVersion ] = func.runtime.split('-', 2);
96
- const imageName = `openruntimes/${runtimeName}:v3 -${runtimeVersion}`;
101
+ const imageName = `openruntimes/${runtimeName}:${openRuntimesVersion} -${runtimeVersion}`;
97
102
98
103
const tool = systemTools[runtimeName];
99
104
100
105
const functionDir = path.join(process.cwd(), func.path);
101
106
102
107
const id = `${new Date().getTime().toString(16)}${Math.round(Math.random() * 1000000000).toString(16)}`;
103
- const params = ['run', '--rm', '--name', id, '-i', '-e', 'OPEN_RUNTIMES_SECRET=', '-p', `${port}:3000`, '-v', `${functionDir}/:/mnt/code:rw`, imageName, 'sh', '-c', ` helpers/start.sh "${tool.startCommand}"`];
108
+ const params = ['run', '--rm', '--name', id, '-i', '-e', 'OPEN_RUNTIMES_SECRET=', '-p', `${port}:3000`, '-v', `${functionDir}/.appwrite/logs:/mnt/logs:rw`, '-v', `${functionDir}/ :/mnt/code:rw`, imageName, 'sh', '-c', ` helpers/start.sh "${tool.startCommand}"`];
104
109
105
110
const execProcess = childProcess.spawn('docker', params, {
106
111
stdio: 'pipe',
@@ -211,19 +216,29 @@ const runFunction = async ({ port, engine, functionId } = {}) => {
211
216
212
217
let watcherRunning = false;
213
218
219
+ childProcess.execSync(`sudo mkdir -p ${path.join(process.cwd(), func.path, '.appwrite/logs')}`, {
220
+ pwd: path.join(process.cwd(), func.path)
221
+ });
222
+ chokidar.watch('.appwrite/logs', {
223
+ cwd: path.join(process.cwd(), func.path),
224
+ ignoreInitial: true,
225
+ }).on('all', async (event, filePath) => {
226
+ console.log(fs.readFileSync(path.join(process.cwd(), func.path, filePath)).toString());
227
+ });
228
+
214
229
chokidar.watch('.', {
215
230
cwd: path.join(process.cwd(), func.path),
216
231
ignoreInitial: true,
217
- ignored: [ ...(func.ignore ?? []), 'code.tar.gz', '.appwrite' ]
218
- }).on('all', async (event, path ) => {
232
+ ignored: [ ...(func.ignore ?? []), 'code.tar.gz', '.appwrite', '.appwrite/', '.appwrite/*', '.appwrite/**', '.appwrite/*.*', '.appwrite/**/*.*' ]
233
+ }).on('all', async (event, filePath ) => {
219
234
if(watcherRunning) {
220
235
info("File change detected but ignored, because live reload is already being ran.");
221
236
return;
222
237
}
223
238
224
239
watcherRunning = true;
225
240
226
- log('Detected a change in ' + path );
241
+ log('Detected a change in ' + filePath );
227
242
228
243
try {
229
244
log('Stopping the function ...');
@@ -232,11 +247,63 @@ const runFunction = async ({ port, engine, functionId } = {}) => {
232
247
await dockerStop(id);
233
248
}
234
249
235
- if(tool.isCompiled || tool.dependencyFiles.includes(path )) {
250
+ if(tool.isCompiled || tool.dependencyFiles.includes(filePath )) {
236
251
await dockerBuild(func);
237
252
await dockerStart(func, port);
238
253
} else {
239
- // TODO: Update code.tar.gz with latest changes
254
+ // TODO: Some try-catch approach, to rebuild if fails
255
+ log('Hot swapping function files ...');
256
+
257
+ const functionPath = path.join(process.cwd(), func.path);
258
+ const hotSwapPath = path.join(functionPath, '.appwrite/hot-swap');
259
+ const buildPath = path.join(functionPath, 'code.tar.gz')
260
+
261
+ // TODO: Using Node code, no sudo
262
+ childProcess.execSync(`sudo mkdir -p ${hotSwapPath} && sudo chmod 777 ${buildPath} ${hotSwapPath} && sudo tar -zxf ${buildPath} -C ${hotSwapPath}`, {
263
+ pwd: path.join(process.cwd(), func.path)
264
+ });
265
+
266
+ const ignorer = ignore();
267
+ ignorer.add('.appwrite');
268
+
269
+ if (func.ignore) {
270
+ ignorer.add(func.ignore);
271
+ }
272
+
273
+ // TODO: Better approach
274
+ const filesToCopy = getAllFiles(functionPath).map((file) => path.relative(functionPath, file)).filter((file) => !ignorer.ignores(file));
275
+
276
+ const copyCommands = [];
277
+ for(const f of filesToCopy) {
278
+ const filePath = path.join(hotSwapPath, f);
279
+ copyCommands.push(`sudo rm -rf ${filePath}`);
280
+
281
+ const fileDir = path.dirname(filePath);
282
+ copyCommands.push(`sudo mkdir -p ${fileDir}`);
283
+
284
+ const sourcePath = path.join(functionPath, f);
285
+ copyCommands.push(`sudo cp ${sourcePath} ${filePath}`);
286
+ }
287
+ childProcess.execSync(copyCommands.join(" && "), {
288
+ pwd: path.join(process.cwd(), func.path)
289
+ });
290
+
291
+ console.log(path.join(process.cwd(), func.path, '.appwrite'));
292
+ /*
293
+ childProcess.execSync("sudo chmod -R 777 .", {
294
+ pwd: path.join(process.cwd(), func.path, '.appwrite')
295
+ });
296
+ */
297
+
298
+ childProcess.execSync(`sudo tar -C ${hotSwapPath} --exclude code.tar.gz -zcf ${buildPath} .`, {
299
+ pwd: hotSwapPath
300
+ });
301
+
302
+ // TODO: Using Node code
303
+ childProcess.execSync(`sudo rm -rf ${hotSwapPath}`, {
304
+ pwd: path.join(process.cwd(), func.path)
305
+ });
306
+
240
307
await dockerStart(func, port);
241
308
}
242
309
} catch(err) {
0 commit comments