serverless-esbuild
Version:
Serverless plugin for zero-config JavaScript and TypeScript code bundling using extremely fast esbuild
205 lines • 9.63 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.NPM = void 0;
const effect_1 = require("effect");
const ramda_1 = require("ramda");
const path = __importStar(require("path"));
const utils_1 = require("../utils");
/**
* NPM packager.
*/
class NPM {
get lockfileName() {
return 'package-lock.json';
}
get copyPackageSectionNames() {
return [];
}
get mustCopyModules() {
return true;
}
async getNpmMajorVersion(cwd) {
const command = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';
const args = ['--version'];
const processOutput = await (0, utils_1.spawnProcess)(command, args, { cwd });
const version = processOutput.stdout.trim();
const [major] = version.split('.');
if (major) {
return parseInt(major, 10);
}
throw new Error('Unable to get major npm version');
}
async getProdDependencies(cwd, depth) {
const npmMajorVersion = await this.getNpmMajorVersion(cwd);
const prodFlag = npmMajorVersion >= 7 ? '--omit=dev' : '-prod';
const noDepthFlag = npmMajorVersion >= 7 ? '-all' : null;
// Get first level dependency graph
const command = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';
const args = [
'ls',
'-json',
prodFlag, // Only prod dependencies
'-long',
depth ? `-depth=${depth}` : noDepthFlag,
].filter(effect_1.Predicate.isString);
const ignoredNpmErrors = [
{ npmError: 'extraneous', log: false },
{ npmError: 'missing', log: false },
{ npmError: 'peer dep missing', log: true },
{ npmError: 'code ELSPROBLEMS', log: false },
];
let parsedDeps;
try {
const processOutput = await (0, utils_1.spawnProcess)(command, args, { cwd });
parsedDeps = JSON.parse(processOutput.stdout);
}
catch (err) {
if (err instanceof utils_1.SpawnError) {
// Only exit with an error if we have critical npm errors for 2nd level inside
// Split the stderr by \n character to get the npm ERR! plaintext lines, ignore additional JSON blob (emitted by npm >=7)
// see https://github.com/serverless-heaven/serverless-webpack/pull/782 and https://github.com/floydspace/serverless-esbuild/issues/288
const lines = (0, ramda_1.split)('\n', err.stderr);
const npmErrors = (0, ramda_1.takeWhile)((line) => line !== '{', lines);
const hasThrowableErrors = npmErrors.every((error) => !(0, ramda_1.isEmpty)(error) &&
!(0, ramda_1.any)((ignoredError) => (0, ramda_1.startsWith)(`npm ERR! ${ignoredError.npmError}`, error), ignoredNpmErrors));
if (!hasThrowableErrors && !(0, ramda_1.isEmpty)(err.stdout)) {
return { stdout: err.stdout };
}
}
throw err;
}
const basePath = parsedDeps.path;
const convertTrees = (currentTree, rootDeps, currentDeps = rootDeps) => {
return Object.entries(currentTree).reduce((deps, [name, tree]) => {
if (tree.path === path.join(basePath, 'node_modules', name)) {
// Module path is in the root folder
// If this isn't the root of the tree
if (rootDeps !== deps) {
// Set it as resolved
// eslint-disable-next-line no-param-reassign
deps[name] ?? (deps[name] = {
version: tree.version,
isRootDep: true,
});
}
if (tree._deduped || (!(0, ramda_1.isEmpty)(tree._dependencies) && !tree.dependencies)) {
// Edge case - When it is de-duped this record will not contain the dependency tree.
// _deduped is for v6 (Object.keys(tree._dependencies).length && !tree.dependencies) for v7
// We can just ignore storing this at the root because it does not contain the tree we are after
// "samchungy-dep-b": {
// "version": "3.0.0",
// "name": "samchungy-dep-b",
// "resolved": "https://registry.npmjs.org/samchungy-dep-b/-/samchungy-dep-b-3.0.0.tgz",
// "integrity": "sha512-fy6RAnofLSnLHgOUmgsFz0ZFnJcJeNHT+qUfHJ7daIFlBaciRDR6v5sdWm7mAM2EzQ1KFf2hmKJVFZgthVeCAw==",
// "_id": "samchungy-dep-b@3.0.0",
// "extraneous": false,
// "path": "/Users/schung/me/serverless-esbuild/examples/individually/node_modules/samchungy-dep-b",
// "_dependencies": {
// "samchungy-dep-c": "^1.0.0",
// "samchungy-dep-d": "^1.0.0"
// },
// "devDependencies": {},
// "peerDependencies": {}
// }
}
else {
// This is a root node_modules dependency
// eslint-disable-next-line no-param-reassign
rootDeps[name] ?? (rootDeps[name] = {
version: tree.version,
...(tree.dependencies &&
!(0, ramda_1.isEmpty)(tree.dependencies) && {
dependencies: convertTrees(tree.dependencies, rootDeps, {}),
}),
});
}
return deps;
}
// Module is only installed within the node_modules of this dep. Iterate through it's dep tree
// eslint-disable-next-line no-param-reassign
deps[name] ?? (deps[name] = {
version: tree.version,
...(tree.dependencies &&
!(0, ramda_1.isEmpty)(tree.dependencies) && {
dependencies: convertTrees(tree.dependencies, rootDeps, {}),
}),
});
return deps;
}, currentDeps);
};
return {
...(parsedDeps.dependencies &&
!(0, ramda_1.isEmpty)(parsedDeps.dependencies) && {
dependencies: convertTrees(parsedDeps.dependencies, {}),
}),
};
}
/**
* We should not be modifying 'package-lock.json'
* because this file should be treated as internal to npm.
*
* Rebase package-lock is a temporary workaround and must be
* removed as soon as https://github.com/npm/npm/issues/19183 gets fixed.
*/
rebaseLockfile(pathToPackageRoot, lockfile) {
if (lockfile.version) {
// eslint-disable-next-line no-param-reassign
lockfile.version = this._rebaseFileReferences(pathToPackageRoot, lockfile.version);
}
if (lockfile.dependencies) {
for (const lockedDependency in lockfile.dependencies) {
this.rebaseLockfile(pathToPackageRoot, lockedDependency);
}
}
return lockfile;
}
async install(cwd, extraArgs) {
const command = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';
const args = ['install', ...extraArgs];
await (0, utils_1.spawnProcess)(command, args, { cwd });
}
async prune(cwd) {
const command = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';
const args = ['prune'];
await (0, utils_1.spawnProcess)(command, args, { cwd });
}
async runScripts(cwd, scriptNames) {
const command = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';
await Promise.all(scriptNames.map((scriptName) => {
const args = ['run', scriptName];
return (0, utils_1.spawnProcess)(command, args, { cwd });
}));
}
_rebaseFileReferences(pathToPackageRoot, moduleVersion) {
if (/^file:[^/]{2}/.test(moduleVersion)) {
const filePath = (0, ramda_1.replace)(/^file:/, '', moduleVersion);
return (0, ramda_1.replace)(/\\/g, '/', `file:${pathToPackageRoot}/${filePath}`);
}
return moduleVersion;
}
}
exports.NPM = NPM;
//# sourceMappingURL=npm.js.map