UNPKG

@aquaori/deplens

Version:

A precise dependency analysis tool for npm and pnpm projects

115 lines 4.71 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseNpmLockfile = parseNpmLockfile; const fs_1 = __importDefault(require("fs")); const compare_versions_1 = require("compare-versions"); /** * 解析 npm lockfile * @param manifestPath lockfile 路径 * @returns 依赖列表和检查计数 */ function parseNpmLockfile(manifestPath, ignoreList) { // 读取并解析 lockfile const rootManifest = JSON.parse(fs_1.default.readFileSync(manifestPath, 'utf-8')); // 获取不同类型的依赖 const rootProd = rootManifest["packages"][""].dependencies || {}; const rootPeer = rootManifest["packages"][""].peerDependencies || {}; const rootOpt = rootManifest["packages"][""].optionalDependencies || {}; const rootDev = rootManifest["packages"][""].devDependencies || {}; delete rootManifest["packages"][""]; const depSource = rootManifest["packages"]; // 收集被其他包使用的依赖 const usedByOthers = new Map(); let checkCount = 0; for (const [key, pkg] of Object.entries(depSource)) { if (key === '' || !pkg || typeof pkg !== 'object') continue; const p = pkg; [ p.dependencies || {}, p.peerDependencies || {}, p.optionalDependencies || {} ].forEach(obj => { Object.entries(obj).forEach(([depName, depRange]) => { if (typeof depRange !== 'string') return; const ver = depRange.replace(/\(.+?\)+/g, ''); if (!usedByOthers.has(depName)) usedByOthers.set(depName, new Set()); usedByOthers.get(depName).add(ver); checkCount++; }); }); } // 构建锁文件中的依赖包列表 const lockFilePkg = []; const rootDeclared = new Map(); Object.entries({ ...rootProd, ...rootPeer, ...rootOpt, ...rootDev }) .forEach(([name, ver]) => rootDeclared.set(name, ver)); for (const [name, version] of rootDeclared) { if (ignoreList.includes(name)) continue; const pureVersion = version.replace(/[\^\*\~\=\>\<]/g, ''); let usedVersions = usedByOthers.get(name); let usedVersionsList = new Set(); for (let ver of usedVersions || []) { const verList = ver ? ver.split(" || ") : []; for (let ver of verList) { const verName = ver; if (verName != "") usedVersionsList.add(verName); } } let isUsed = false; for (let ver of usedVersionsList) { if (ver == "*") { isUsed = true; break; } if ((0, compare_versions_1.satisfies)(pureVersion, ver)) { isUsed = true; break; } } if (!isUsed) { let preciseVersion = "0"; if (typeof version == "string") preciseVersion = version.replace(/\(.+?\)+/g, ''); else if (typeof version == "object") preciseVersion = version.version.replace(/\(.+?\)+/g, ''); const previousPkgIndex = lockFilePkg.findIndex(dep => dep.name == name); const previousPkg = previousPkgIndex >= 0 ? lockFilePkg[previousPkgIndex] : null; let previousVersion = previousPkg?.version ?? []; if (previousPkg !== null && previousVersion !== "") { if (previousVersion.length != 0 && !previousPkg?.usage) previousVersion = [...previousVersion, preciseVersion]; else previousVersion = [preciseVersion]; } else { previousVersion = [preciseVersion]; } ; if (previousVersion.length != 1) previousVersion = [previousVersion.join(" & @")]; if (previousPkgIndex >= 0 && previousPkg !== null) { lockFilePkg[previousPkgIndex].version = previousVersion; } else lockFilePkg.push({ name, type: '', version: previousVersion, usage: isUsed, isDev: Object.prototype.hasOwnProperty.call(rootDev, name) }); } } // 按名称排序 lockFilePkg.sort((a, b) => a.name.localeCompare(b.name)); return { dependencies: lockFilePkg, checkCount }; } //# sourceMappingURL=npm.js.map