serverless-webpack-layers
Version:
Plugin for the Serverless framework that offers AWS Lambda layer management using webpack
240 lines (191 loc) • 32.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getExternalModules = getExternalModules;
var _webpack = _interopRequireDefault(require("webpack"));
var _lodash = _interopRequireDefault(require("lodash.merge"));
var _path = _interopRequireDefault(require("path"));
var _fs = _interopRequireDefault(require("fs"));
var _glob = _interopRequireDefault(require("glob"));
var _isBuiltinModule = _interopRequireDefault(require("is-builtin-module"));
var _utils = require("./utils");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
global['PACKAGING_LABELS'] = true;
const compile = file => new Promise((resolve, reject) => (0, _webpack.default)(file).run((err, stats) => err ? reject(err) : resolve(stats)));
const defaultWebpackConfig = {
clean: true,
backupFileType: 'js',
configPath: './webpack.config.js',
discoverModules: true,
forceInclude: [],
forceExclude: []
};
function isExternalModule(module) {
return Object.prototype.hasOwnProperty.call(module, 'externalType');
}
function getExternalModuleName(module) {
const regex = module.externalType ? new RegExp(`^external ${module.externalType} "(.*)"$`) : /^external "(.*)"$/;
const pathParts = regex.exec(typeof module.identifier === 'function' ? module.identifier() : module.identifier);
if (pathParts === null) return '';
const modulePath = pathParts[1];
const pathComponents = modulePath.split('/');
const main = pathComponents[0]; // this is a package within a namespace
if (main.charAt(0) == '@') {
return `${main}/${pathComponents[1]}`;
}
return main.replace('external', '').replace(module.externalType, '').replace(/"/g, '').trim();
}
function getExternalModulesFromStats(stats) {
if (!stats || !stats.compilation.chunks) {
return [];
}
const externals = new Set();
const modules = new Set(stats.compilation.modules);
for (const chunk of stats.compilation.chunks) {
stats.compilation.chunkGraph.getChunkModules(chunk).forEach(module => modules.add(module));
} // Explore each module within the chunk (built inputs):
for (const module of modules) {
if (!isExternalModule(module)) continue;
if ((0, _isBuiltinModule.default)(getExternalModuleName(module))) continue;
const externalModuleName = getExternalModuleName(module);
if (externalModuleName === undefined) continue;
externals.add(externalModuleName);
}
return Array.from(externals);
}
const globPromise = pattern => new Promise((resolve, reject) => (0, _glob.default)(pattern, (err, matches) => err ? reject(err) : resolve(matches)));
async function findEntriesSpecified(specifiedEntries) {
let entries = specifiedEntries;
if (typeof specifiedEntries === 'string') {
entries = [specifiedEntries];
}
if (!Array.isArray(entries)) {
return [];
}
const allMapped = await Promise.all(entries.map(globPromise));
return allMapped.reduce((arr, list) => arr.concat(list), []);
}
async function resolvedEntries(sls, layerRefName) {
const newEntries = {};
const backupFileType = sls.service.custom.layerConfig.backupFileType ?? sls.service.custom.layerConfig.webpack.backupFileType ?? 'default';
for (const func of Object.values(sls.service.functions)) {
if (!(0, _utils.isFunctionDefinition)(func)) {
console.error(`This library doesn't currently support functions with an image`);
continue;
}
const {
handler,
layers = [],
entry: specifiedEntries = [],
shouldLayer = true
} = func;
if (!shouldLayer) continue;
if (!layers.some(layer => layer.Ref === layerRefName)) continue;
const matchedSpecifiedEntries = await findEntriesSpecified(specifiedEntries);
for (const entry of matchedSpecifiedEntries) {
newEntries[entry] = _path.default.resolve(entry);
}
const match = handler.match(/^(((?:[^\/\n]+\/)+)?[^.]+(.jsx?|.tsx?)?)/);
if (!match) continue;
const [handlerName,, folderName = ''] = match;
const files = await _fs.default.promises.readdir(_path.default.resolve(folderName.replace(/\/$/, '')));
let fileName = handlerName.replace(folderName, '');
const filteredFiles = files.filter(file => file.startsWith(fileName));
if (filteredFiles.length > 1) {
fileName += `.${backupFileType}`;
} else {
fileName = filteredFiles[0];
}
newEntries[handlerName] = _path.default.resolve(_path.default.join(folderName, fileName));
}
return newEntries;
}
function getForceModulesFromLayer(sls, layerRefName) {
let forceIncludeAll = [];
let forceExcludeAll = [];
const layer = sls.service.layers[layerRefName.replace(/LambdaLayer$/, '').toLocaleLowerCase()];
if (!layer) {
return {
forceInclude: forceIncludeAll,
forceExclude: forceExcludeAll
};
}
const {
forceInclude = [],
forceExclude = []
} = layer;
forceIncludeAll = forceIncludeAll.concat(forceInclude);
forceExcludeAll = forceIncludeAll.concat(forceExclude);
return {
forceInclude: forceIncludeAll,
forceExclude: forceExcludeAll
};
}
function getForceModulesFromFunctions(sls, layerRefName) {
let forceIncludeAll = [];
let forceExcludeAll = [];
for (const func of Object.values(sls.service.functions)) {
if (!(0, _utils.isFunctionDefinition)(func)) {
console.error(`This library doesn't currently support functions with an image`);
continue;
}
const {
layers = [],
forceInclude = [],
forceExclude = []
} = func;
if (!layers.some(layer => layer.Ref === layerRefName)) continue;
forceIncludeAll = forceIncludeAll.concat(forceInclude);
forceExcludeAll = forceIncludeAll.concat(forceExclude);
}
return {
forceInclude: forceIncludeAll,
forceExclude: forceExcludeAll
};
}
async function getExternalModules(sls, layerRefName) {
try {
const runPath = process.cwd();
const {
webpack: webpackConfigUnmerged = {}
} = sls.service.custom.layerConfig;
const webpackConfig = (0, _lodash.default)(defaultWebpackConfig, webpackConfigUnmerged);
const forceInclude = [...webpackConfig.forceInclude, ...(Array.isArray(webpackConfigUnmerged.forceInclude) ? webpackConfigUnmerged.forceInclude : [])];
const forceExclude = [...webpackConfig.forceExclude, ...(Array.isArray(webpackConfigUnmerged.forceExclude) ? webpackConfigUnmerged.forceExclude : [])];
const {
configPath = './webpack.config.js',
discoverModules = true
} = webpackConfig;
let config = await require(_path.default.join(runPath, configPath));
if (typeof config === 'function') {
let newConfigValue = config();
if (newConfigValue instanceof Promise) {
newConfigValue = await newConfigValue;
}
config = newConfigValue;
}
const {
forceInclude: forceIncludeFunction = [],
forceExclude: forceExcludeFunction = []
} = getForceModulesFromFunctions(sls, layerRefName);
const {
forceInclude: forceIncludeLayer = [],
forceExclude: forceExcludeLayer = []
} = getForceModulesFromLayer(sls, layerRefName);
config.entry = await resolvedEntries(sls, layerRefName);
const packageJson = await require(_path.default.join(runPath, 'package.json'));
let moduleNames = new Set();
if (discoverModules) {
const stats = await compile(config);
moduleNames = new Set(getExternalModulesFromStats(stats));
}
forceInclude.concat(forceIncludeFunction).concat(forceIncludeLayer).forEach(forceIncludedModule => moduleNames.add(forceIncludedModule));
forceExclude.concat(forceExcludeFunction).concat(forceExcludeLayer).forEach(forceExcludedModule => moduleNames.delete(forceExcludedModule));
return Array.from(moduleNames).map(name => packageJson.dependencies[name] || packageJson.devDependencies[name] ? `${name}@${packageJson.dependencies[name] || packageJson.devDependencies[name]}` : name);
} catch (err) {
console.error(err);
throw err;
}
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9leHRlcm5hbC50cyJdLCJuYW1lcyI6WyJnbG9iYWwiLCJjb21waWxlIiwiZmlsZSIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwicnVuIiwiZXJyIiwic3RhdHMiLCJkZWZhdWx0V2VicGFja0NvbmZpZyIsImNsZWFuIiwiYmFja3VwRmlsZVR5cGUiLCJjb25maWdQYXRoIiwiZGlzY292ZXJNb2R1bGVzIiwiZm9yY2VJbmNsdWRlIiwiZm9yY2VFeGNsdWRlIiwiaXNFeHRlcm5hbE1vZHVsZSIsIm1vZHVsZSIsIk9iamVjdCIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImdldEV4dGVybmFsTW9kdWxlTmFtZSIsInJlZ2V4IiwiZXh0ZXJuYWxUeXBlIiwiUmVnRXhwIiwicGF0aFBhcnRzIiwiZXhlYyIsImlkZW50aWZpZXIiLCJtb2R1bGVQYXRoIiwicGF0aENvbXBvbmVudHMiLCJzcGxpdCIsIm1haW4iLCJjaGFyQXQiLCJyZXBsYWNlIiwidHJpbSIsImdldEV4dGVybmFsTW9kdWxlc0Zyb21TdGF0cyIsImNvbXBpbGF0aW9uIiwiY2h1bmtzIiwiZXh0ZXJuYWxzIiwiU2V0IiwibW9kdWxlcyIsImNodW5rIiwiY2h1bmtHcmFwaCIsImdldENodW5rTW9kdWxlcyIsImZvckVhY2giLCJhZGQiLCJleHRlcm5hbE1vZHVsZU5hbWUiLCJ1bmRlZmluZWQiLCJBcnJheSIsImZyb20iLCJnbG9iUHJvbWlzZSIsInBhdHRlcm4iLCJtYXRjaGVzIiwiZmluZEVudHJpZXNTcGVjaWZpZWQiLCJzcGVjaWZpZWRFbnRyaWVzIiwiZW50cmllcyIsImlzQXJyYXkiLCJhbGxNYXBwZWQiLCJhbGwiLCJtYXAiLCJyZWR1Y2UiLCJhcnIiLCJsaXN0IiwiY29uY2F0IiwicmVzb2x2ZWRFbnRyaWVzIiwic2xzIiwibGF5ZXJSZWZOYW1lIiwibmV3RW50cmllcyIsInNlcnZpY2UiLCJjdXN0b20iLCJsYXllckNvbmZpZyIsIndlYnBhY2siLCJmdW5jIiwidmFsdWVzIiwiZnVuY3Rpb25zIiwiY29uc29sZSIsImVycm9yIiwiaGFuZGxlciIsImxheWVycyIsImVudHJ5Iiwic2hvdWxkTGF5ZXIiLCJzb21lIiwibGF5ZXIiLCJSZWYiLCJtYXRjaGVkU3BlY2lmaWVkRW50cmllcyIsInBhdGgiLCJtYXRjaCIsImhhbmRsZXJOYW1lIiwiZm9sZGVyTmFtZSIsImZpbGVzIiwiZnMiLCJwcm9taXNlcyIsInJlYWRkaXIiLCJmaWxlTmFtZSIsImZpbHRlcmVkRmlsZXMiLCJmaWx0ZXIiLCJzdGFydHNXaXRoIiwibGVuZ3RoIiwiam9pbiIsImdldEZvcmNlTW9kdWxlc0Zyb21MYXllciIsImZvcmNlSW5jbHVkZUFsbCIsImZvcmNlRXhjbHVkZUFsbCIsInRvTG9jYWxlTG93ZXJDYXNlIiwiZ2V0Rm9yY2VNb2R1bGVzRnJvbUZ1bmN0aW9ucyIsImdldEV4dGVybmFsTW9kdWxlcyIsInJ1blBhdGgiLCJwcm9jZXNzIiwiY3dkIiwid2VicGFja0NvbmZpZ1VubWVyZ2VkIiwid2VicGFja0NvbmZpZyIsImNvbmZpZyIsInJlcXVpcmUiLCJuZXdDb25maWdWYWx1ZSIsImZvcmNlSW5jbHVkZUZ1bmN0aW9uIiwiZm9yY2VFeGNsdWRlRnVuY3Rpb24iLCJmb3JjZUluY2x1ZGVMYXllciIsImZvcmNlRXhjbHVkZUxheWVyIiwicGFja2FnZUpzb24iLCJtb2R1bGVOYW1lcyIsImZvcmNlSW5jbHVkZWRNb2R1bGUiLCJmb3JjZUV4Y2x1ZGVkTW9kdWxlIiwiZGVsZXRlIiwibmFtZSIsImRlcGVuZGVuY2llcyIsImRldkRlcGVuZGVuY2llcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUVBOztBQUdBOzs7O0FBSUFBLE1BQU0sQ0FBQyxrQkFBRCxDQUFOLEdBQTZCLElBQTdCOztBQUVBLE1BQU1DLE9BQU8sR0FBSUMsSUFBRCxJQUNkLElBQUlDLE9BQUosQ0FBWSxDQUFDQyxPQUFELEVBQVVDLE1BQVYsS0FDVixz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QkFGVixFQUdHdkUsT0FISCxDQUdXMkUsbUJBQW1CLElBQUlELFdBQVcsQ0FBQ3pFLEdBQVosQ0FBZ0IwRSxtQkFBaEIsQ0FIbEM7QUFJQXpHLElBQUFBLFlBQVksQ0FDVGlELE1BREgsQ0FDVW1ELG9CQURWLEVBRUduRCxNQUZILENBRVVxRCxpQkFGVixFQUdHeEUsT0FISCxDQUdXNEUsbUJBQW1CLElBQUlGLFdBQVcsQ0FBQ0csTUFBWixDQUFtQkQsbUJBQW5CLENBSGxDO0FBSUEsV0FBT3hFLEtBQUssQ0FBQ0MsSUFBTixDQUFXcUUsV0FBWCxFQUF3QjNELEdBQXhCLENBQTRCK0QsSUFBSSxJQUNyQ0wsV0FBVyxDQUFDTSxZQUFaLENBQXlCRCxJQUF6QixLQUFrQ0wsV0FBVyxDQUFDTyxlQUFaLENBQTRCRixJQUE1QixDQUFsQyxHQUNLLEdBQUVBLElBQUssSUFBR0wsV0FBVyxDQUFDTSxZQUFaLENBQXlCRCxJQUF6QixLQUFrQ0wsV0FBVyxDQUFDTyxlQUFaLENBQTRCRixJQUE1QixDQUFrQyxFQURuRixHQUVJQSxJQUhDLENBQVA7QUFLRCxHQS9DRCxDQStDRSxPQUFPcEgsR0FBUCxFQUFZO0FBQ1pxRSxJQUFBQSxPQUFPLENBQUNDLEtBQVIsQ0FBY3RFLEdBQWQ7QUFDQSxVQUFNQSxHQUFOO0FBQ0Q7QUFDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB3ZWJwYWNrLCB7IEV4dGVybmFsTW9kdWxlIH0gZnJvbSAnd2VicGFjayc7XG5pbXBvcnQgbWVyZ2UgZnJvbSAnbG9kYXNoLm1lcmdlJztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IGZzIGZyb20gJ2ZzJztcbmltcG9ydCBnbG9iIGZyb20gJ2dsb2InO1xuaW1wb3J0IFNlcnZlcmxlc3MgZnJvbSAnc2VydmVybGVzcyc7XG5pbXBvcnQgaXNCdWlsdGluTW9kdWxlIGZyb20gJ2lzLWJ1aWx0aW4tbW9kdWxlJztcbmltcG9ydCB7IFN0YXRzLCBNb2R1bGUgfSBmcm9tICd3ZWJwYWNrJztcbmltcG9ydCB7IE1heWJlIH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBpc0Z1bmN0aW9uRGVmaW5pdGlvbiB9IGZyb20gJy4vdXRpbHMnO1xuXG5kZWNsYXJlIGNvbnN0IGdsb2JhbDogQ3VzdG9tR2xvYmFsO1xuXG5nbG9iYWxbJ1BBQ0tBR0lOR19MQUJFTFMnXSA9IHRydWU7XG5cbmNvbnN0IGNvbXBpbGUgPSAoZmlsZTogd2VicGFjay5Db25maWd1cmF0aW9uKTogUHJvbWlzZTxNYXliZTxTdGF0cz4+ID0+XG4gIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+XG4gICAgd2VicGFjayhmaWxlKS5ydW4oKGVycj86IE1heWJlPEVycm9yPiwgc3RhdHM/OiBTdGF0cykgPT4gKGVyciA/IHJlamVjdChlcnIpIDogcmVzb2x2ZShzdGF0cykpKVxuICApO1xuXG5jb25zdCBkZWZhdWx0V2VicGFja0NvbmZpZyA9IHtcbiAgY2xlYW46IHRydWUsXG4gIGJhY2t1cEZpbGVUeXBlOiAnanMnLFxuICBjb25maWdQYXRoOiAnLi93ZWJwYWNrLmNvbmZpZy5qcycsXG4gIGRpc2NvdmVyTW9kdWxlczogdHJ1ZSxcbiAgZm9yY2VJbmNsdWRlOiBbXSxcbiAgZm9yY2VFeGNsdWRlOiBbXSxcbn07XG5cbmZ1bmN0aW9uIGlzRXh0ZXJuYWxNb2R1bGUobW9kdWxlOiBNb2R1bGUpOiBtb2R1bGUgaXMgRXh0ZXJuYWxNb2R1bGUge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1vZHVsZSwgJ2V4dGVybmFsVHlwZScpO1xufVxuXG5mdW5jdGlvbiBnZXRFeHRlcm5hbE1vZHVsZU5hbWUobW9kdWxlOiBFeHRlcm5hbE1vZHVsZSk6IHN0cmluZyB7XG4gIGNvbnN0IHJlZ2V4ID0gbW9kdWxlLmV4dGVybmFsVHlwZSA/IG5ldyBSZWdFeHAoYF5leHRlcm5hbCAke21vZHVsZS5leHRlcm5hbFR5cGV9IFwiKC4qKVwiJGApIDogL15leHRlcm5hbCBcIiguKilcIiQvO1xuICBjb25zdCBwYXRoUGFydHMgPSByZWdleC5leGVjKFxuICAgIHR5cGVvZiBtb2R1bGUuaWRlbnRpZmllciA9PT0gJ2Z1bmN0aW9uJyA/IG1vZHVsZS5pZGVudGlmaWVyKCkgOiAobW9kdWxlLmlkZW50aWZpZXIgYXMgdW5rbm93biBhcyBzdHJpbmcpXG4gICk7XG4gIGlmIChwYXRoUGFydHMgPT09IG51bGwpIHJldHVybiAnJztcbiAgY29uc3QgbW9kdWxlUGF0aCA9IHBhdGhQYXJ0c1sxXTtcbiAgY29uc3QgcGF0aENvbXBvbmVudHMgPSBtb2R1bGVQYXRoLnNwbGl0KCcvJyk7XG4gIGNvbnN0IG1haW4gPSBwYXRoQ29tcG9uZW50c1swXTtcblxuICAvLyB0aGlzIGlzIGEgcGFja2FnZSB3aXRoaW4gYSBuYW1lc3BhY2VcbiAgaWYgKG1haW4uY2hhckF0KDApID09ICdAJykge1xuICAgIHJldHVybiBgJHttYWlufS8ke3BhdGhDb21wb25lbnRzWzFdfWA7XG4gIH1cblxuICByZXR1cm4gbWFpbi5yZXBsYWNlKCdleHRlcm5hbCcsICcnKS5yZXBsYWNlKG1vZHVsZS5leHRlcm5hbFR5cGUsICcnKS5yZXBsYWNlKC9cIi9nLCAnJykudHJpbSgpO1xufVxuXG5mdW5jdGlvbiBnZXRFeHRlcm5hbE1vZHVsZXNGcm9tU3RhdHMoc3RhdHM6IE1heWJlPFN0YXRzPik6IHN0cmluZ1tdIHtcbiAgaWYgKCFzdGF0cyB8fCAhc3RhdHMuY29tcGlsYXRpb24uY2h1bmtzKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIGNvbnN0IGV4dGVybmFsczogU2V0PHN0cmluZz4gPSBuZXcgU2V0KCk7XG4gIGNvbnN0IG1vZHVsZXMgPSBuZXcgU2V0PE1vZHVsZT4oc3RhdHMuY29tcGlsYXRpb24ubW9kdWxlcyk7XG4gIGZvciAoY29uc3QgY2h1bmsgb2Ygc3RhdHMuY29tcGlsYXRpb24uY2h1bmtzKSB7XG4gICAgc3RhdHMuY29tcGlsYXRpb24uY2h1bmtHcmFwaC5nZXRDaHVua01vZHVsZXMoY2h1bmspLmZvckVhY2gobW9kdWxlID0+IG1vZHVsZXMuYWRkKG1vZHVsZSkpO1xuICB9XG5cbiAgLy8gRXhwbG9yZSBlYWNoIG1vZHVsZSB3aXRoaW4gdGhlIGNodW5rIChidWlsdCBpbnB1dHMpOlxuICBmb3IgKGNvbnN0IG1vZHVsZSBvZiBtb2R1bGVzKSB7XG4gICAgaWYgKCFpc0V4dGVybmFsTW9kdWxlKG1vZHVsZSkpIGNvbnRpbnVlO1xuICAgIGlmIChpc0J1aWx0aW5Nb2R1bGUoZ2V0RXh0ZXJuYWxNb2R1bGVOYW1lKG1vZHVsZSkpKSBjb250aW51ZTtcbiAgICBjb25zdCBleHRlcm5hbE1vZHVsZU5hbWUgPSBnZXRFeHRlcm5hbE1vZHVsZU5hbWUobW9kdWxlKTtcbiAgICBpZiAoZXh0ZXJuYWxNb2R1bGVOYW1lID09PSB1bmRlZmluZWQpIGNvbnRpbnVlO1xuICAgIGV4dGVybmFscy5hZGQoZXh0ZXJuYWxNb2R1bGVOYW1lKTtcbiAgfVxuICByZXR1cm4gQXJyYXkuZnJvbShleHRlcm5hbHMpO1xufVxuXG5jb25zdCBnbG9iUHJvbWlzZSA9IChwYXR0ZXJuOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZ1tdPiA9PlxuICBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiBnbG9iKHBhdHRlcm4sIChlcnIsIG1hdGNoZXMpID0+IChlcnIgPyByZWplY3QoZXJyKSA6IHJlc29sdmUobWF0Y2hlcykpKSk7XG5cbmFzeW5jIGZ1bmN0aW9uIGZpbmRFbnRyaWVzU3BlY2lmaWVkKHNwZWNpZmllZEVudHJpZXM6IHN0cmluZyB8IHN0cmluZ1tdKSB7XG4gIGxldCBlbnRyaWVzID0gc3BlY2lmaWVkRW50cmllcztcbiAgaWYgKHR5cGVvZiBzcGVjaWZpZWRFbnRyaWVzID09PSAnc3RyaW5nJykge1xuICAgIGVudHJpZXMgPSBbc3BlY2lmaWVkRW50cmllc107XG4gIH1cbiAgaWYgKCFBcnJheS5pc0FycmF5KGVudHJpZXMpKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIGNvbnN0IGFsbE1hcHBlZCA9IGF3YWl0IFByb21pc2UuYWxsKGVudHJpZXMubWFwKGdsb2JQcm9taXNlKSk7XG4gIHJldHVybiBhbGxNYXBwZWQucmVkdWNlKChhcnIsIGxpc3QpID0+IGFyci5jb25jYXQobGlzdCksIFtdKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZWRFbnRyaWVzKHNsczogU2VydmVybGVzcywgbGF5ZXJSZWZOYW1lOiBzdHJpbmcpIHtcbiAgY29uc3QgbmV3RW50cmllczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICBjb25zdCBiYWNrdXBGaWxlVHlwZSA9XG4gICAgc2xzLnNlcnZpY2UuY3VzdG9tLmxheWVyQ29uZmlnLmJhY2t1cEZpbGVUeXBlID8/IHNscy5zZXJ2aWNlLmN1c3RvbS5sYXllckNvbmZpZy53ZWJwYWNrLmJhY2t1cEZpbGVUeXBlID8/ICdkZWZhdWx0JztcbiAgZm9yIChjb25zdCBmdW5jIG9mIE9iamVjdC52YWx1ZXMoc2xzLnNlcnZpY2UuZnVuY3Rpb25zKSkge1xuICAgIGlmICghaXNGdW5jdGlvbkRlZmluaXRpb24oZnVuYykpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoYFRoaXMgbGlicmFyeSBkb2Vzbid0IGN1cnJlbnRseSBzdXBwb3J0IGZ1bmN0aW9ucyB3aXRoIGFuIGltYWdlYCk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgY29uc3QgeyBoYW5kbGVyLCBsYXllcnMgPSBbXSwgZW50cnk6IHNwZWNpZmllZEVudHJpZXMgPSBbXSwgc2hvdWxkTGF5ZXIgPSB0cnVlIH0gPSBmdW5jO1xuICAgIGlmICghc2hvdWxkTGF5ZXIpIGNvbnRpbnVlO1xuICAgIGlmICghbGF5ZXJzLnNvbWUobGF5ZXIgPT4gbGF5ZXIuUmVmID09PSBsYXllclJlZk5hbWUpKSBjb250aW51ZTtcbiAgICBjb25zdCBtYXRjaGVkU3BlY2lmaWVkRW50cmllcyA9IGF3YWl0IGZpbmRFbnRyaWVzU3BlY2lmaWVkKHNwZWNpZmllZEVudHJpZXMpO1xuICAgIGZvciAoY29uc3QgZW50cnkgb2YgbWF0Y2hlZFNwZWNpZmllZEVudHJpZXMpIHtcbiAgICAgIG5ld0VudHJpZXNbZW50cnldID0gcGF0aC5yZXNvbHZlKGVudHJ5KTtcbiAgICB9XG4gICAgY29uc3QgbWF0Y2ggPSBoYW5kbGVyLm1hdGNoKC9eKCgoPzpbXlxcL1xcbl0rXFwvKSspP1teLl0rKC5qc3g/fC50c3g/KT8pLyk7XG4gICAgaWYgKCFtYXRjaCkgY29udGludWU7XG4gICAgY29uc3QgW2hhbmRsZXJOYW1lLCAsIGZvbGRlck5hbWUgPSAnJ10gPSBtYXRjaDtcbiAgICBjb25zdCBmaWxlcyA9IGF3YWl0IGZzLnByb21pc2VzLnJlYWRkaXIocGF0aC5yZXNvbHZlKGZvbGRlck5hbWUucmVwbGFjZSgvXFwvJC8sICcnKSkpO1xuICAgIGxldCBmaWxlTmFtZSA9IGhhbmRsZXJOYW1lLnJlcGxhY2UoZm9sZGVyTmFtZSwgJycpO1xuICAgIGNvbnN0IGZpbHRlcmVkRmlsZXMgPSBmaWxlcy5maWx0ZXIoZmlsZSA9PiBmaWxlLnN0YXJ0c1dpdGgoZmlsZU5hbWUpKTtcbiAgICBpZiAoZmlsdGVyZWRGaWxlcy5sZW5ndGggPiAxKSB7XG4gICAgICBmaWxlTmFtZSArPSBgLiR7YmFja3VwRmlsZVR5cGV9YDtcbiAgICB9IGVsc2Uge1xuICAgICAgZmlsZU5hbWUgPSBmaWx0ZXJlZEZpbGVzWzBdO1xuICAgIH1cbiAgICBuZXdFbnRyaWVzW2hhbmRsZXJOYW1lXSA9IHBhdGgucmVzb2x2ZShwYXRoLmpvaW4oZm9sZGVyTmFtZSwgZmlsZU5hbWUpKTtcbiAgfVxuICByZXR1cm4gbmV3RW50cmllcztcbn1cbmZ1bmN0aW9uIGdldEZvcmNlTW9kdWxlc0Zyb21MYXllcihzbHM6IFNlcnZlcmxlc3MsIGxheWVyUmVmTmFtZTogc3RyaW5nKSB7XG4gIGxldCBmb3JjZUluY2x1ZGVBbGw6IHN0cmluZ1tdID0gW107XG4gIGxldCBmb3JjZUV4Y2x1ZGVBbGw6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IGxheWVyID0gc2xzLnNlcnZpY2UubGF5ZXJzW2xheWVyUmVmTmFtZS5yZXBsYWNlKC9MYW1iZGFMYXllciQvLCAnJykudG9Mb2NhbGVMb3dlckNhc2UoKV07XG4gIGlmICghbGF5ZXIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgZm9yY2VJbmNsdWRlOiBmb3JjZUluY2x1ZGVBbGwsXG4gICAgICBmb3JjZUV4Y2x1ZGU6IGZvcmNlRXhjbHVkZUFsbCxcbiAgICB9O1xuICB9XG4gIGNvbnN0IHsgZm9yY2VJbmNsdWRlID0gW10sIGZvcmNlRXhjbHVkZSA9IFtdIH0gPSBsYXllcjtcbiAgZm9yY2VJbmNsdWRlQWxsID0gZm9yY2VJbmNsdWRlQWxsLmNvbmNhdChmb3JjZUluY2x1ZGUpO1xuICBmb3JjZUV4Y2x1ZGVBbGwgPSBmb3JjZUluY2x1ZGVBbGwuY29uY2F0KGZvcmNlRXhjbHVkZSk7XG4gIHJldHVybiB7XG4gICAgZm9yY2VJbmNsdWRlOiBmb3JjZUluY2x1ZGVBbGwsXG4gICAgZm9yY2VFeGNsdWRlOiBmb3JjZUV4Y2x1ZGVBbGwsXG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldEZvcmNlTW9kdWxlc0Zyb21GdW5jdGlvbnMoc2xzOiBTZXJ2ZXJsZXNzLCBsYXllclJlZk5hbWU6IHN0cmluZykge1xuICBsZXQgZm9yY2VJbmNsdWRlQWxsOiBzdHJpbmdbXSA9IFtdO1xuICBsZXQgZm9yY2VFeGNsdWRlQWxsOiBzdHJpbmdbXSA9IFtdO1xuICBmb3IgKGNvbnN0IGZ1bmMgb2YgT2JqZWN0LnZhbHVlcyhzbHMuc2VydmljZS5mdW5jdGlvbnMpKSB7XG4gICAgaWYgKCFpc0Z1bmN0aW9uRGVmaW5pdGlvbihmdW5jKSkge1xuICAgICAgY29uc29sZS5lcnJvcihgVGhpcyBsaWJyYXJ5IGRvZXNuJ3QgY3VycmVudGx5IHN1cHBvcnQgZnVuY3Rpb25zIHdpdGggYW4gaW1hZ2VgKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCB7IGxheWVycyA9IFtdLCBmb3JjZUluY2x1ZGUgPSBbXSwgZm9yY2VFeGNsdWRlID0gW10gfSA9IGZ1bmM7XG4gICAgaWYgKCFsYXllcnMuc29tZShsYXllciA9PiBsYXllci5SZWYgPT09IGxheWVyUmVmTmFtZSkpIGNvbnRpbnVlO1xuICAgIGZvcmNlSW5jbHVkZUFsbCA9IGZvcmNlSW5jbHVkZUFsbC5jb25jYXQoZm9yY2VJbmNsdWRlKTtcbiAgICBmb3JjZUV4Y2x1ZGVBbGwgPSBmb3JjZUluY2x1ZGVBbGwuY29uY2F0KGZvcmNlRXhjbHVkZSk7XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBmb3JjZUluY2x1ZGU6IGZvcmNlSW5jbHVkZUFsbCxcbiAgICBmb3JjZUV4Y2x1ZGU6IGZvcmNlRXhjbHVkZUFsbCxcbiAgfTtcbn1cblxudHlwZSBXZWJwYWNrQ29uZmlnQXNPYmpPckZ1bmMgPVxuICB8IHdlYnBhY2suQ29uZmlndXJhdGlvblxuICB8ICgoKSA9PiB3ZWJwYWNrLkNvbmZpZ3VyYXRpb24pXG4gIHwgKCgpID0+IFByb21pc2U8d2VicGFjay5Db25maWd1cmF0aW9uPik7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRFeHRlcm5hbE1vZHVsZXMoc2xzOiBTZXJ2ZXJsZXNzLCBsYXllclJlZk5hbWU6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBydW5QYXRoID0gcHJvY2Vzcy5jd2QoKTtcbiAgICBjb25zdCB7IHdlYnBhY2s6IHdlYnBhY2tDb25maWdVbm1lcmdlZCA9IHt9IH0gPSBzbHMuc2VydmljZS5jdXN0b20ubGF5ZXJDb25maWc7XG4gICAgY29uc3Qgd2VicGFja0NvbmZpZyA9IG1lcmdlKGRlZmF1bHRXZWJwYWNrQ29uZmlnLCB3ZWJwYWNrQ29uZmlnVW5tZXJnZWQpO1xuICAgIGNvbnN0IGZvcmNlSW5jbHVkZSA9IFtcbiAgICAgIC4uLndlYnBhY2tDb25maWcuZm9yY2VJbmNsdWRlLFxuICAgICAgLi4uKEFycmF5LmlzQXJyYXkod2VicGFja0NvbmZpZ1VubWVyZ2VkLmZvcmNlSW5jbHVkZSkgPyB3ZWJwYWNrQ29uZmlnVW5tZXJnZWQuZm9yY2VJbmNsdWRlIDogW10pLFxuICAgIF07XG4gICAgY29uc3QgZm9yY2VFeGNsdWRlID0gW1xuICAgICAgLi4ud2VicGFja0NvbmZpZy5mb3JjZUV4Y2x1ZGUsXG4gICAgICAuLi4oQXJyYXkuaXNBcnJheSh3ZWJwYWNrQ29uZmlnVW5tZXJnZWQuZm9yY2VFeGNsdWRlKSA/IHdlYnBhY2tDb25maWdVbm1lcmdlZC5mb3JjZUV4Y2x1ZGUgOiBbXSksXG4gICAgXTtcbiAgICBjb25zdCB7IGNvbmZpZ1BhdGggPSAnLi93ZWJwYWNrLmNvbmZpZy5qcycsIGRpc2NvdmVyTW9kdWxlcyA9IHRydWUgfSA9IHdlYnBhY2tDb25maWc7XG4gICAgbGV0IGNvbmZpZzogV2VicGFja0NvbmZpZ0FzT2JqT3JGdW5jID0gYXdhaXQgcmVxdWlyZShwYXRoLmpvaW4ocnVuUGF0aCwgY29uZmlnUGF0aCkpO1xuICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBsZXQgbmV3Q29uZmlnVmFsdWUgPSBjb25maWcoKTtcbiAgICAgIGlmIChuZXdDb25maWdWYWx1ZSBpbnN0YW5jZW9mIFByb21pc2UpIHtcbiAgICAgICAgbmV3Q29uZmlnVmFsdWUgPSBhd2FpdCBuZXdDb25maWdWYWx1ZTtcbiAgICAgIH1cbiAgICAgIGNvbmZpZyA9IG5ld0NvbmZpZ1ZhbHVlO1xuICAgIH1cbiAgICBjb25zdCB7IGZvcmNlSW5jbHVkZTogZm9yY2VJbmNsdWRlRnVuY3Rpb24gPSBbXSwgZm9yY2VFeGNsdWRlOiBmb3JjZUV4Y2x1ZGVGdW5jdGlvbiA9IFtdIH0gPVxuICAgICAgZ2V0Rm9yY2VNb2R1bGVzRnJvbUZ1bmN0aW9ucyhzbHMsIGxheWVyUmVmTmFtZSk7XG4gICAgY29uc3QgeyBmb3JjZUluY2x1ZGU6IGZvcmNlSW5jbHVkZUxheWVyID0gW10sIGZvcmNlRXhjbHVkZTogZm9yY2VFeGNsdWRlTGF5ZXIgPSBbXSB9ID0gZ2V0Rm9yY2VNb2R1bGVzRnJvbUxheWVyKFxuICAgICAgc2xzLFxuICAgICAgbGF5ZXJSZWZOYW1lXG4gICAgKTtcbiAgICBjb25maWcuZW50cnkgPSBhd2FpdCByZXNvbHZlZEVudHJpZXMoc2xzLCBsYXllclJlZk5hbWUpO1xuICAgIGNvbnN0IHBhY2thZ2VKc29uID0gYXdhaXQgcmVxdWlyZShwYXRoLmpvaW4ocnVuUGF0aCwgJ3BhY2thZ2UuanNvbicpKTtcbiAgICBsZXQgbW9kdWxlTmFtZXM6IFNldDxzdHJpbmc+ID0gbmV3IFNldCgpO1xuICAgIGlmIChkaXNjb3Zlck1vZHVsZXMpIHtcbiAgICAgIGNvbnN0IHN0YXRzID0gYXdhaXQgY29tcGlsZShjb25maWcpO1xuICAgICAgbW9kdWxlTmFtZXMgPSBuZXcgU2V0KGdldEV4dGVybmFsTW9kdWxlc0Zyb21TdGF0cyhzdGF0cykpO1xuICAgIH1cbiAgICBmb3JjZUluY2x1ZGVcbiAgICAgIC5jb25jYXQoZm9yY2VJbmNsdWRlRnVuY3Rpb24pXG4gICAgICAuY29uY2F0KGZvcmNlSW5jbHVkZUxheWVyKVxuICAgICAgLmZvckVhY2goZm9yY2VJbmNsdWRlZE1vZHVsZSA9PiBtb2R1bGVOYW1lcy5hZGQoZm9yY2VJbmNsdWRlZE1vZHVsZSkpO1xuICAgIGZvcmNlRXhjbHVkZVxuICAgICAgLmNvbmNhdChmb3JjZUV4Y2x1ZGVGdW5jdGlvbilcbiAgICAgIC5jb25jYXQoZm9yY2VFeGNsdWRlTGF5ZXIpXG4gICAgICAuZm9yRWFjaChmb3JjZUV4Y2x1ZGVkTW9kdWxlID0+IG1vZHVsZU5hbWVzLmRlbGV0ZShmb3JjZUV4Y2x1ZGVkTW9kdWxlKSk7XG4gICAgcmV0dXJuIEFycmF5LmZyb20obW9kdWxlTmFtZXMpLm1hcChuYW1lID0+XG4gICAgICBwYWNrYWdlSnNvbi5kZXBlbmRlbmNpZXNbbmFtZV0gfHwgcGFja2FnZUpzb24uZGV2RGVwZW5kZW5jaWVzW25hbWVdXG4gICAgICAgID8gYCR7bmFtZX1AJHtwYWNrYWdlSnNvbi5kZXBlbmRlbmNpZXNbbmFtZV0gfHwgcGFja2FnZUpzb24uZGV2RGVwZW5kZW5jaWVzW25hbWVdfWBcbiAgICAgICAgOiBuYW1lXG4gICAgKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgIHRocm93IGVycjtcbiAgfVxufVxuIl19