UNPKG

snyk-nodejs-lockfile-parser

Version:
175 lines 7.91 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getChildNode = exports.getGraphDependencies = exports.getTopLevelDeps = exports.addPkgNodeToGraph = void 0; exports.parsePkgJson = parsePkgJson; const errors_1 = require("../errors"); const errors_2 = require("../errors"); const parsers_1 = require("../parsers"); const pkgJson_1 = require("../aliasesPreprocessors/pkgJson"); const addPkgNodeToGraph = (depGraphBuilder, node, options) => { return depGraphBuilder.addPkgNode({ name: node.name, version: node.version }, node.id, { labels: Object.assign(Object.assign(Object.assign(Object.assign({ scope: node.isDev ? 'dev' : 'prod' }, (options.isCyclic && { pruned: 'cyclic' })), (options.isWorkspacePkg && { pruned: 'true' })), (node.missingLockFileEntry && { missingLockFileEntry: 'true' })), (node.alias && { alias: `${node.alias.aliasName}=>${node.alias.aliasTargetDepName}@${node.version}`, })), }); }; exports.addPkgNodeToGraph = addPkgNodeToGraph; /** * Get top level dependencies from the given package json object which is parsed from a package.json file. * This includes both prod dependencies and dev dependencies supposing includeDevDeps is supported. */ const getTopLevelDeps = (pkgJson, options) => { const prodDeps = (0, exports.getGraphDependencies)(pkgJson.dependencies || {}, { isDev: false, }); const devDeps = (0, exports.getGraphDependencies)(pkgJson.devDependencies || {}, { isDev: true, }); const optionalDeps = options.includeOptionalDeps ? (0, exports.getGraphDependencies)(pkgJson.optionalDependencies || {}, { isDev: false, isOptional: true, }) : {}; const peerDeps = options.includePeerDeps ? (0, exports.getGraphDependencies)(pkgJson.peerDependencies || {}, { isDev: false }) : {}; const deps = Object.assign(Object.assign(Object.assign({}, prodDeps), optionalDeps), peerDeps); if (pkgJson.aliases) { for (const alias of Object.keys(pkgJson.aliases)) { // Only add alias metadata to dependencies that are actually in deps if (deps[alias]) { deps[alias] = Object.assign(Object.assign({}, deps[alias]), { alias: Object.assign({}, pkgJson.aliases[alias]) }); } } } if (options.includeDevDeps) { // Ensure dev dependency 'isDev' flags are correctly set. // Dev dependencies are applied last to override shared keys with regular dependencies. return Object.assign(Object.assign({}, deps), devDeps); } // For includeDevDeps option set to false, simulate pnpm install --prod // by excluding all devDependencies, // ignoring potential duplicates in other dependency lists. // https://pnpm.io/cli/install#--prod--p return Object.keys(deps) .filter((packageName) => !devDeps.hasOwnProperty(packageName)) .reduce((result, packageName) => { result[packageName] = deps[packageName]; return result; }, {}); }; exports.getTopLevelDeps = getTopLevelDeps; /** * Converts dependencies parsed from the a lock file to a dependencies object required by the graph. * For example, { 'mime-db': '~1.12.0' } will be converted to { 'mime-db': { version: '~1.12.0', isDev: true/false } }. */ const getGraphDependencies = (dependencies, options) => { return Object.entries(dependencies).reduce((pnpmDeps, [name, semver]) => { pnpmDeps[name] = { version: semver, isDev: options.isDev, isOptional: options.isOptional || false, }; return pnpmDeps; }, {}); }; exports.getGraphDependencies = getGraphDependencies; function parsePkgJson(pkgJsonContent) { try { const parsedPkgJson = JSON.parse(pkgJsonContent); if (!parsedPkgJson.name) { parsedPkgJson.name = 'package.json'; } return parsedPkgJson; } catch (e) { throw new errors_1.InvalidUserInputError('package.json parsing failed with error ' + e.message); } } const getChildNode = (name, depInfo, pkgs, strictOutOfSync, includeOptionalDeps) => { var _a, _b, _c; const childNodeKey = `${name}@${depInfo.version}`; let childNode; // Check if this lockfile entry is for an aliased package // by looking for a corresponding npm: entry in the lockfile let aliasInfo = depInfo.alias; if (!aliasInfo && pkgs[childNodeKey]) { // Look for any key in pkgs that matches the pattern: name@npm:* // and has the same version as our current entry for (const key in pkgs) { if (key.startsWith(`${name}@npm:`)) { const pkgEntry = pkgs[key]; if (pkgEntry.version === pkgs[childNodeKey].version) { // Extract the npm: portion and parse it using the shared helper const npmPortion = key.substring(name.length + 1); // Remove "name@" prefix const parsed = (0, pkgJson_1.parseNpmAlias)(npmPortion); if (parsed) { const targetPkgName = parsed.packageName; // Only add alias info if the alias name is different from the target name if (targetPkgName !== name) { aliasInfo = { aliasName: name, aliasTargetDepName: targetPkgName, semver: parsed.version, version: parsed.version, }; } break; } } } } } if (!pkgs[childNodeKey]) { // Handle optional dependencies that don't have separate package entries if (depInfo.isOptional) { childNode = { id: childNodeKey, name: (_a = aliasInfo === null || aliasInfo === void 0 ? void 0 : aliasInfo.aliasTargetDepName) !== null && _a !== void 0 ? _a : name, version: depInfo.version, dependencies: {}, isDev: depInfo.isDev, missingLockFileEntry: true, alias: aliasInfo, }; } else if (strictOutOfSync && !/^file:/.test(depInfo.version)) { throw new errors_2.OutOfSyncError(childNodeKey, parsers_1.LockfileType.yarn); } else { childNode = { id: childNodeKey, name: (_b = aliasInfo === null || aliasInfo === void 0 ? void 0 : aliasInfo.aliasTargetDepName) !== null && _b !== void 0 ? _b : name, version: depInfo.version, dependencies: {}, isDev: depInfo.isDev, missingLockFileEntry: true, alias: aliasInfo, }; } } else { const depData = pkgs[childNodeKey]; const dependencies = (0, exports.getGraphDependencies)(depData.dependencies || {}, { isDev: depInfo.isDev, }); const optionalDependencies = includeOptionalDeps ? (0, exports.getGraphDependencies)(depData.optionalDependencies || {}, { isDev: depInfo.isDev, isOptional: true, }) : {}; childNode = { id: `${name}@${depData.version}`, name: (_c = aliasInfo === null || aliasInfo === void 0 ? void 0 : aliasInfo.aliasTargetDepName) !== null && _c !== void 0 ? _c : name, version: depData.version, dependencies: Object.assign(Object.assign({}, dependencies), optionalDependencies), isDev: depInfo.isDev, alias: aliasInfo, }; } return childNode; }; exports.getChildNode = getChildNode; //# sourceMappingURL=util.js.map