serverless-webpack
Version:
Serverless plugin to bundle your javascript with Webpack
162 lines (143 loc) • 4.45 kB
JavaScript
;
const _ = require('lodash');
const BbPromise = require('bluebird');
const childProcess = require('child_process');
function guid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}
/**
* Remove the specified module from the require cache.
* @param {string} moduleName
*/
function purgeCache(moduleName) {
return searchAndProcessCache(moduleName, function (mod) {
delete require.cache[mod.id];
}).then(() => {
_.forEach(_.keys(module.constructor._pathCache), function (cacheKey) {
if (cacheKey.indexOf(moduleName) > 0) {
delete module.constructor._pathCache[cacheKey];
}
});
return BbPromise.resolve();
});
}
function searchAndProcessCache(moduleName, processor) {
let mod_src = require.resolve(moduleName);
const visitedModules = [];
if (mod_src && (mod_src = require.cache[mod_src]) !== undefined) {
const modStack = [mod_src];
while (!_.isEmpty(modStack)) {
const mod = modStack.pop();
if (!_.includes(visitedModules, mod)) {
visitedModules.push(mod);
Array.prototype.push.apply(modStack, mod.children);
processor(mod);
}
}
}
return BbPromise.resolve();
}
class SpawnError extends Error {
constructor(message, stdout, stderr) {
super(message);
this.stdout = stdout;
this.stderr = stderr;
}
toString() {
return `${this.message}\n${this.stderr}`;
}
}
/**
* Executes a child process without limitations on stdout and stderr.
* On error (exit code is not 0), it rejects with a SpawnProcessError that contains the stdout and stderr streams,
* on success it returns the streams in an object.
* @param {string} command - Command
* @param {string[]} [args] - Arguments
* @param {Object} [options] - Options for child_process.spawn
*/
function spawnProcess(command, args, options) {
return new BbPromise((resolve, reject) => {
const child = childProcess.spawn(command, args, {
...options,
// nodejs 20 on windows doesn't allow `.cmd` command to run without `shell: true`
// https://github.com/serverless-heaven/serverless-webpack/issues/1791
shell: /^win/.test(process.platform)
});
let stdout = '';
let stderr = '';
// Configure stream encodings
child.stdout.setEncoding('utf8');
child.stderr.setEncoding('utf8');
// Listen to stream events
child.stdout.on('data', data => {
stdout += data;
});
child.stderr.on('data', data => {
stderr += data;
});
child.on('error', err => {
if (process.env.NODE_ENV === 'test') {
console.error(err);
}
reject(err);
});
child.on('close', exitCode => {
if (exitCode !== 0) {
reject(new SpawnError(`${command} ${_.join(args, ' ')} failed with code ${exitCode}`, stdout, stderr));
} else {
resolve({ stdout, stderr });
}
});
});
}
function safeJsonParse(str) {
try {
return JSON.parse(str);
} catch (e) {
return null;
}
}
function splitLines(str) {
return _.split(str, /\r?\n/);
}
function isNodeRuntime(runtime) {
return runtime.match(/node/);
}
function getAllNodeFunctions() {
const functions = this.serverless.service.getAllFunctions();
return _.filter(functions, funcName => {
const func = this.serverless.service.getFunction(funcName);
// if `uri` or `name` is provided or simple remote image path, it means the
// image isn't built by Serverless so we shouldn't take care of it
if ((func.image && (func.image.uri || func.image.name)) || (func.image && typeof func.image == 'string')) {
return false;
}
return isNodeRuntime(func.runtime || this.serverless.service.provider.runtime || 'nodejs');
});
}
/**
* Given a serverless instance, will return whether the provider is google (as opposed to another
* provider like 'aws')
* @param {*} serverless the serverless instance that holds the configuration
* @returns true if the provider is google, otherwise false
*/
function isProviderGoogle(serverless) {
return _.get(serverless, 'service.provider.name') === 'google';
}
module.exports = {
guid,
purgeCache,
searchAndProcessCache,
SpawnError,
spawnProcess,
safeJsonParse,
splitLines,
getAllNodeFunctions,
isNodeRuntime,
isProviderGoogle
};