UNPKG

rugby

Version:

A Node.js CLI to collect npm package tarballs and assets (including those fetched by pre/postinstall scripts) for offline Artifactory use.

72 lines (62 loc) 2.37 kB
"use strict"; const semver = require("semver"); // Build an ordered list of packages from package-lock.json. The lock already contains full dependency graph. // We keep a Map key -> info, where key is name@version to preserve multiple versions of the same package. // info = { name, version, resolved, integrity } // And a topological-ish order map for deterministic processing. async function discoverDependencyGraph({ projectDir, pkgJson, lockJson, verbose }) { const packages = new Map(); // npm v7+ lockfile v2 has a top-level "packages" map and "dependencies" tree if (lockJson && lockJson.packages) { for (const [nodePath, info] of Object.entries(lockJson.packages)) { if (!info || !info.version) continue; // nodePath "" is the root project if (nodePath === "") continue; const name = info.name || inferNameFromPath(nodePath); const version = info.version; const key = `${name}@${version}`; packages.set(key, { name, version, resolved: info.resolved, integrity: info.integrity, }); } } else if (lockJson && lockJson.dependencies) { // Legacy lockfile v1 function walk(deps) { for (const [name, info] of Object.entries(deps)) { if (info && info.version) { const version = info.version; const key = `${name}@${version}`; packages.set(key, { name, version, resolved: info.resolved, integrity: info.integrity, }); } if (info && info.dependencies) walk(info.dependencies); } } walk(lockJson.dependencies); } // Maintain deterministic order by sorting by name@version const order = new Map(); Array.from(packages.entries()) .sort((a, b) => { const [ak, ai] = a; const [bk, bi] = b; if (ai.name === bi.name) return semver.compare(ai.version, bi.version); return ai.name.localeCompare(bi.name); }) .forEach(([key, info]) => order.set(key, info)); return { packages, order }; } function inferNameFromPath(nodePath) { // lock.packages paths look like node_modules/foo or node_modules/@scope/foo const parts = nodePath.split("node_modules/").filter(Boolean); const last = parts[parts.length - 1]; return last || nodePath || ""; } module.exports = { discoverDependencyGraph };