@ibm-functions/shell-local-plugin
Advanced tools
Comparing version 0.0.13 to 0.0.14
{ | ||
"name": "@ibm-functions/shell-local-plugin", | ||
"version": "0.0.13", | ||
"version": "0.0.14", | ||
"description": "An IBM Cloud Functions Shell plugin that lets users run and debug actions locally in a docker container", | ||
@@ -5,0 +5,0 @@ "main": "plugin.js", |
@@ -594,5 +594,24 @@ /* | ||
/** | ||
* Wrap the given code with the debug harness | ||
* | ||
* @param code the text of the main code | ||
* @param input the JSON structure which is the input parameter | ||
* @param path the (container-local) output path to which we should write the result | ||
* | ||
* @return the text of the harnessed code | ||
*/ | ||
const debugCodeWrapper = (code, input, path) => { | ||
return `\n\n${code}\n\n//below is the debuger code added by Shell \n\nlet debugMainFunc = exports.main ? exports.main : main; \nlet s = debugMainFunc(${JSON.stringify(input)});\nrequire('fs').writeFileSync('${path}', JSON.stringify(s))\n`; | ||
return ` | ||
${code} | ||
// below is the debugger harness | ||
const debugMainFunc = exports.main || main | ||
Promise.resolve(debugMainFunc(${JSON.stringify(input)})) | ||
.then(result => require('fs').writeFileSync('${path}', JSON.stringify(result)))` | ||
} | ||
@@ -605,3 +624,3 @@ | ||
const runActionDebugger = (actionName, functionCode, functionKind, functionInput, isBinary, { ui }, spinnerDiv, returnDiv, dashOptions) => new Promise((resolve, reject) => { | ||
appendIncreContent('Preparing debugger', spinnerDiv) | ||
appendIncreContent('Preparing container', spinnerDiv) | ||
@@ -616,5 +635,7 @@ // this specifies a path inside docker container, so we should not | ||
if(isBinary){ | ||
// then "fileCode" is really the zip contents; we'll extract this below | ||
fileCode = functionCode; | ||
} | ||
else{ | ||
// otherwise, this is a plain action | ||
fileCode = debugCodeWrapper(functionCode, functionInput, resultFilePath); | ||
@@ -641,37 +662,47 @@ } | ||
createTempFolder() | ||
.then(d => { // create a local temp folder | ||
let dirPath = d.path, cleanupCallback = d.cleanupCallback, containerFolderPath = dirPath.substring(dirPath.lastIndexOf('/')+1), entry; | ||
// first, create a local temp folder | ||
createTempFolder().then(({path:dirPath, cleanupCallback}) => { | ||
const containerFolderPath = dirPath.substring(dirPath.lastIndexOf('/') + 1) | ||
fs.outputFile(`${dirPath}/${debugFileName}`, fileCode, isBinary?'base64':undefined) // write file to that local temp folder | ||
.then(() => { | ||
return new Promise((resolve, reject) => { | ||
if(isBinary){ // if it is a zip action, unzip first | ||
extract(`${dirPath}/${debugFileName}`, {dir: `${dirPath}`}, function (err) { | ||
if(err){ | ||
reject(err); | ||
} | ||
else{ | ||
fs.readFile(`${dirPath}/package.json`) // read package.json | ||
.then(data => { | ||
entry = JSON.parse(data).main; | ||
return fs.readFile(`${dirPath}/${entry}`); // get the entry js file | ||
.then(() => new Promise((resolve, reject) => { | ||
if(isBinary){ // if it is a zip action, unzip first | ||
extract(`${dirPath}/${debugFileName}`, { dir: `${dirPath}` }, function (err) { | ||
if(err){ | ||
reject(err); | ||
} | ||
else{ | ||
// see if a package.json exists; if so read it | ||
// in, because there may be a "main" field | ||
// that indicates the name of the file which | ||
// includes the main routine | ||
const packageJsonPath = `${dirPath}/package.json` | ||
fs.pathExists(packageJsonPath) | ||
.then(exists => { | ||
if (exists) { | ||
// yup, we found a package.json, now see if it has a main field | ||
return fs.readFile(packageJsonPath) | ||
.then(data => JSON.parse(data).main || 'index.js') // backup plan: index.js | ||
} else { | ||
// nope, no package.json, so use the default main file | ||
return 'index.js' | ||
} | ||
}) | ||
.then(data => { | ||
let newCode = debugCodeWrapper(data.toString(), functionInput, resultFilePath); // wrap that js file with our runnner code | ||
return fs.outputFile(`${dirPath}/${entry}`, newCode); // write the new file to temp directory | ||
}) | ||
.then(() => {resolve(entry)}) | ||
.then(entry => fs.readFile(`${dirPath}/${entry}`) // read in the entry code, so we can wrap it with debug | ||
.then(data => debugCodeWrapper(data.toString(), functionInput, resultFilePath)) // wrap it! | ||
.then(newCode => fs.outputFile(`${dirPath}/${entry}`, newCode)) // write the new file to temp directory | ||
.then(() => resolve(entry))) // return value: the location of the entry | ||
.catch(reject) | ||
} | ||
}); | ||
} | ||
else { | ||
entry = debugFileName; | ||
resolve(true); | ||
} | ||
}); | ||
}) | ||
.then(() => repl.qexec(`! docker cp ${dirPath} shell-local:/nodejsAction`)) // copy temp dir into container | ||
.then(() => appendIncreContent('Starting the debugger', spinnerDiv)) // status update | ||
.then(() => { | ||
} | ||
}) | ||
} else { | ||
// otherwise, this is a plain (not zip) action | ||
entry = debugFileName; | ||
resolve(entry) // return value: the location of the entry | ||
} | ||
})) | ||
.then(entry => repl.qexec(`! docker cp ${dirPath} shell-local:/nodejsAction`) // copy temp dir into container | ||
.then(() => appendIncreContent('Launching debugger', spinnerDiv)) // status update | ||
.then(() => entry)) | ||
.then(entry => { | ||
// this is where we launch the local debugger, and wait for it to terminate | ||
@@ -678,0 +709,0 @@ // as to why we need to hack for the Waiting for debugger on stderr: |
68336
925