@hyrious/dup
Advanced tools
Comparing version 0.1.2 to 0.1.3
@@ -19,17 +19,28 @@ // src/dup.ts | ||
for (const key in p) { | ||
let pkg; | ||
let ver; | ||
if (key.startsWith("node_modules/")) { | ||
const i = key.lastIndexOf("node_modules/"); | ||
const pkg = key.slice(i + 13); | ||
const ver = p[key].version; | ||
const parts = key.split("/").slice(-2); | ||
if (parts[0][0] === "@") { | ||
pkg = parts.join("/"); | ||
} else { | ||
pkg = parts[1]; | ||
} | ||
ver = p[key].version; | ||
collected.push([pkg, ver]); | ||
} else if (key.startsWith("/")) { | ||
const i = key.lastIndexOf("@"); | ||
const pkg = key.slice(1, i); | ||
const ver = key.slice(i + 1); | ||
} else if (key) { | ||
let line = key; | ||
if (line[0] === '"' || line[0] === "'") | ||
line = line.slice(1); | ||
if (line[0] === "/") | ||
line = line.slice(1); | ||
const i = line.indexOf("@", 1); | ||
pkg = line.slice(0, i); | ||
line = line.slice(i + 1); | ||
const match = line.match(/['",(:]/); | ||
ver = match ? line.slice(0, match.index) : line; | ||
const another = p[line].version; | ||
if (another) | ||
ver = another; | ||
collected.push([pkg, ver]); | ||
} else if (key.includes("@")) { | ||
const i = key.indexOf("@", 1); | ||
const pkg = key.slice(0, i); | ||
const ver = p[key].version; | ||
collected.push([pkg, ver]); | ||
} | ||
@@ -44,15 +55,24 @@ } | ||
if (a.startsWith("lockfileVersion")) { | ||
const re = /^ {2}\/(.+):$/gm; | ||
let match; | ||
do { | ||
match = re.exec(a); | ||
if (match) { | ||
const key = match[1]; | ||
const i = key.indexOf("@", 1); | ||
const pkg = key.slice(0, i); | ||
const j = key.indexOf("(", i); | ||
const ver = key.slice(i + 1, j >= 0 ? j : void 0); | ||
collected.push([pkg, ver]); | ||
const lines = a.split(/\r\n|\n/g); | ||
let working = false; | ||
for (let index = 0; index < lines.length; ++index) { | ||
let line = lines[index]; | ||
if (line) { | ||
if (line[0] !== " ") | ||
working = line.startsWith("packages:"); | ||
else if (working && line[2] && line[2] !== " ") { | ||
line = line.slice(2); | ||
if (line[0] === '"' || line[0] === "'") | ||
line = line.slice(1); | ||
if (line[0] === "/") | ||
line = line.slice(1); | ||
const i = line.indexOf("@", 1); | ||
const pkg = line.slice(0, i); | ||
line = line.slice(i + 1); | ||
const match = line.match(/['",(:]/); | ||
const ver = match ? line.slice(0, match.index) : line; | ||
collected.push([pkg, ver]); | ||
} | ||
} | ||
} while (match); | ||
} | ||
} else if (a.includes("yarn lockfile") || a.includes("__metadata")) { | ||
@@ -59,0 +79,0 @@ const lines = a.split(/\r\n|\n/g); |
{ | ||
"name": "@hyrious/dup", | ||
"type": "module", | ||
"version": "0.1.2", | ||
"version": "0.1.3", | ||
"description": "Find duplicates in your lockfile", | ||
@@ -29,7 +29,8 @@ "author": "hyrious <hyrious@outlook.com>", | ||
"@hyrious/esbuild-dev": "^0.10.5", | ||
"@types/node": "^20.11.16", | ||
"esbuild": "^0.20.0" | ||
"@types/node": "^20.12.7", | ||
"esbuild": "^0.20.2" | ||
}, | ||
"scripts": { | ||
"build": "esbuild-dev build.ts" | ||
"build": "esbuild-dev build.ts", | ||
"lint": "biome check --apply ." | ||
}, | ||
@@ -36,0 +37,0 @@ "bin": "dist/dup-cli.js", |
@@ -25,5 +25,6 @@ /** | ||
// NPM: key is "" (self) or "node_modules/{pkg}..." (matching file system) | ||
// PNPM: key is "/{pkg}@{version}" | ||
// PNPM: key is "/{pkg}@{version}(...)" (v6) or "{pkg}@{version}(...)" (v9) | ||
readonly packages: { readonly [key: string]: unknown }; | ||
// Yarn: its root keys are "name@spec, name@spec2", name "__metadata" is reserved | ||
// so PNPM v9 can be conflict with Yarn's lockfile | ||
// value is { version: "resolved version" } | ||
@@ -40,17 +41,35 @@ readonly [key: string]: unknown; | ||
for (const key in p) { | ||
let pkg: string; | ||
let ver: string; | ||
// NPM: "node_modules/path/to/{package-name}": { "version": {version} } | ||
if (key.startsWith("node_modules/")) { | ||
const i = key.lastIndexOf("node_modules/"); | ||
const pkg = key.slice(i + 13); | ||
const ver = (p[key] as { version: string }).version; | ||
const parts = key.split("/").slice(-2); | ||
if (parts[0][0] === "@") { | ||
pkg = parts.join("/"); | ||
} else { | ||
pkg = parts[1]; | ||
} | ||
ver = (p[key] as { version: string }).version; | ||
collected.push([pkg, ver]); | ||
} else if (key.startsWith("/")) { | ||
const i = key.lastIndexOf("@"); | ||
const pkg = key.slice(1, i); | ||
const ver = key.slice(i + 1); | ||
} | ||
// PNPM and Yarn: pkg@ver, pkg@spec, 'pkg@ver', "pkg@spec", /pkg@ver | ||
else if (key) { | ||
let line = key; | ||
// Skip ' " | ||
if (line[0] === '"' || line[0] === "'") line = line.slice(1); | ||
// Skip / | ||
if (line[0] === "/") line = line.slice(1); | ||
// Consume pkg name, pkg[@]ver | ||
const i = line.indexOf("@", 1); | ||
pkg = line.slice(0, i); | ||
// Consume pkg version or spec | ||
line = line.slice(i + 1); | ||
const match = line.match(/['",(:]/); | ||
ver = match ? line.slice(0, match.index) : line; | ||
// If the value has version, use that one (so current 'ver' is a spec) | ||
const another = (p[line] as { version?: string }).version; | ||
if (another) ver = another; | ||
collected.push([pkg, ver]); | ||
} else if (key.includes("@")) { | ||
const i = key.indexOf("@", 1); | ||
const pkg = key.slice(0, i); | ||
const ver = (p[key] as { version: string }).version; | ||
collected.push([pkg, ver]); | ||
} | ||
@@ -66,15 +85,26 @@ } | ||
if (a.startsWith("lockfileVersion")) { | ||
const re = /^ {2}\/(.+):$/gm; | ||
let match: RegExpMatchArray | null; | ||
do { | ||
match = re.exec(a); | ||
if (match) { | ||
const key = match[1]; | ||
const i = key.indexOf("@", 1); | ||
const pkg = key.slice(0, i); | ||
const j = key.indexOf("(", i); | ||
const ver = key.slice(i + 1, j >= 0 ? j : void 0); | ||
collected.push([pkg, ver]); | ||
const lines = a.split(/\r\n|\n/g); | ||
let working = false; | ||
for (let index = 0; index < lines.length; ++index) { | ||
let line = lines[index]; | ||
if (line) { | ||
if (line[0] !== " ") working = line.startsWith("packages:"); | ||
else if (working && line[2] && line[2] !== " ") { | ||
// Skip leading spaces | ||
line = line.slice(2); | ||
// Skip ' " | ||
if (line[0] === '"' || line[0] === "'") line = line.slice(1); | ||
// Skip / | ||
if (line[0] === "/") line = line.slice(1); | ||
// Extract pkg name | ||
const i = line.indexOf("@", 1); | ||
const pkg = line.slice(0, i); | ||
// Extract version | ||
line = line.slice(i + 1); | ||
const match = line.match(/['",(:]/); | ||
const ver = match ? line.slice(0, match.index) : line; | ||
collected.push([pkg, ver]); | ||
} | ||
} | ||
} while (match); | ||
} | ||
} | ||
@@ -81,0 +111,0 @@ // Yarn |
14554
342