@aquaori/deplens
Version:
A precise dependency analysis tool for npm and pnpm projects
105 lines • 4.72 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parsePnpmLockfile = parsePnpmLockfile;
const fs_1 = __importDefault(require("fs"));
const js_yaml_1 = __importDefault(require("js-yaml"));
/**
* 解析 pnpm lockfile
* @param manifestPath lockfile 路径
* @returns 依赖列表和检查计数
*/
function parsePnpmLockfile(manifestPath, ignoreList) {
// 读取并解析 lockfile
const rootManifest = js_yaml_1.default.load(fs_1.default.readFileSync(manifestPath, 'utf-8'));
let lockVersion = 0;
lockVersion = rootManifest.lockfileVersion;
// 获取不同类型的依赖
const rootProd = lockVersion == 6 ? rootManifest.dependencies || {} : rootManifest['importers']['.']?.dependencies || {};
const rootPeer = lockVersion == 6 ? rootManifest.peerDependencies || {} : rootManifest['importers']['.']?.peerDependencies || {};
const rootOpt = lockVersion == 6 ? rootManifest.optionalDependencies || {} : rootManifest['importers']['.']?.optionalDependencies || {};
const rootDev = lockVersion == 6 ? rootManifest.devDependencies || {} : rootManifest['importers']['.']?.devDependencies || {};
const depSource = lockVersion == 6 ? rootManifest.packages || {} : rootManifest.snapshots || {};
// 收集被其他包使用的依赖
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;
let pureVersion;
if (typeof version == "object") {
pureVersion = version.version.replace(/\(.+?\)+/g, '');
}
else {
pureVersion = version.replace(/[\^\*\~\=\>\<]/g, '');
}
let usedVersions = usedByOthers.get(name);
let usedVersionsList = usedVersions || new Set();
let isUsed = usedVersionsList ? usedVersionsList.has(pureVersion) : false;
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=pnpm.js.map