trawly 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +301 -19
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +287 -9
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/commands/add.ts","../src/sources/osv.ts","../src/scanner.ts","../src/extractors/npm-package-lock.ts","../src/types.ts","../src/installer/pm-detect.ts","../src/installer/runner.ts","../src/installer/spec-parser.ts","../src/installer/version-resolver.ts","../src/reporters/json.ts","../src/reporters/table.ts","../src/reporters/banner.ts"],"sourcesContent":["import { Command, InvalidArgumentError } from \"commander\";\nimport kleur from \"kleur\";\nimport { reportAdd, runAdd } from \"./commands/add.js\";\nimport {\n buildInstallCommand,\n buildRemoveCommand,\n detectPackageManager,\n type PackageManager,\n} from \"./installer/pm-detect.js\";\nimport { runPackageManager } from \"./installer/runner.js\";\nimport { reportJson } from \"./reporters/json.js\";\nimport { reportTable } from \"./reporters/table.js\";\nimport { meetsThreshold, ScanInputError, scanProject } from \"./scanner.js\";\nimport type { FailOnLevel } from \"./types.js\";\n\nconst FAIL_ON_VALUES: FailOnLevel[] = [\n \"critical\",\n \"high\",\n \"moderate\",\n \"low\",\n \"none\",\n];\nconst FORMAT_VALUES = [\"table\", \"json\"] as const;\ntype Format = (typeof FORMAT_VALUES)[number];\n\nconst PM_VALUES: PackageManager[] = [\"npm\", \"pnpm\", \"yarn\", \"bun\"];\n\nconst EXIT = {\n ok: 0,\n findings: 1,\n operational: 2,\n invalidInput: 3,\n} as const;\n\nfunction parseFailOn(value: string): FailOnLevel {\n if (!FAIL_ON_VALUES.includes(value as FailOnLevel)) {\n throw new InvalidArgumentError(\n `must be one of: ${FAIL_ON_VALUES.join(\", \")}`,\n );\n }\n return value as FailOnLevel;\n}\n\nfunction parseFormat(value: string): Format {\n if (!FORMAT_VALUES.includes(value as Format)) {\n throw new InvalidArgumentError(\n `must be one of: ${FORMAT_VALUES.join(\", \")}`,\n );\n }\n return value as Format;\n}\n\nfunction parsePm(value: string): PackageManager {\n if (!PM_VALUES.includes(value as PackageManager)) {\n throw new InvalidArgumentError(`must be one of: ${PM_VALUES.join(\", \")}`);\n }\n return value as PackageManager;\n}\n\nconst TRAWLY_VERSION = \"0.1.0\";\n\nconst program = new Command();\n\nprogram\n .name(\"trawly\")\n .description(\n \"Dependency sanity scanner. Checks installed npm packages against the OSV advisory database.\",\n )\n .version(TRAWLY_VERSION)\n .enablePositionalOptions()\n .exitOverride((err) => {\n if (err.code === \"commander.helpDisplayed\" || err.code === \"commander.help\") {\n process.exit(EXIT.ok);\n }\n if (err.code === \"commander.version\") process.exit(EXIT.ok);\n process.exit(EXIT.invalidInput);\n });\n\nprogram\n .command(\"scan\", { isDefault: true })\n .description(\n \"Scan a project and gate on findings. Exits non-zero when --fail-on is met. Use `inspect` for a log-only run.\",\n )\n .argument(\"[path]\", \"Project directory to scan\", \".\")\n .option(\"--lockfile <path>\", \"Explicit path to package-lock.json\")\n .option(\n \"--format <format>\",\n \"Output format: table | json\",\n parseFormat,\n \"table\" as Format,\n )\n .option(\n \"--fail-on <level>\",\n `Exit non-zero when a finding meets this severity (${FAIL_ON_VALUES.join(\"|\")})`,\n parseFailOn,\n \"high\" as FailOnLevel,\n )\n .option(\"--prod\", \"Only scan production dependencies (excludes dev)\")\n .option(\"--include-dev\", \"Include dev dependencies (default)\")\n .option(\"--no-cache\", \"Bypass any local cache\")\n .option(\n \"-v, --details\",\n \"Show one row per advisory (full table). Default groups by package.\",\n )\n .option(\n \"-q, --summary\",\n \"Show only the one-line severity summary. Mutually exclusive with --details.\",\n )\n .action(async (path: string, opts: ScanCliOptions) => {\n await runScanCommand(path, opts, { gate: true });\n });\n\nprogram\n .command(\"inspect\")\n .description(\n \"Scan a project and print findings without gating. Always exits 0 unless an operational error occurs. Use `scan` for CI gating.\",\n )\n .argument(\"[path]\", \"Project directory to scan\", \".\")\n .option(\"--lockfile <path>\", \"Explicit path to package-lock.json\")\n .option(\n \"--format <format>\",\n \"Output format: table | json\",\n parseFormat,\n \"table\" as Format,\n )\n .option(\"--prod\", \"Only scan production dependencies (excludes dev)\")\n .option(\"--include-dev\", \"Include dev dependencies (default)\")\n .option(\"--no-cache\", \"Bypass any local cache\")\n .option(\n \"-v, --details\",\n \"Show one row per advisory (full table). Default groups by package.\",\n )\n .option(\n \"-q, --summary\",\n \"Show only the one-line severity summary. Mutually exclusive with --details.\",\n )\n .action(async (path: string, opts: InspectCliOptions) => {\n await runScanCommand(\n path,\n { ...opts, failOn: \"none\" as FailOnLevel },\n { gate: false },\n );\n });\n\nprogram\n .command(\"add\")\n .description(\n \"Resolve, scan, and install packages. Vulnerable packages are blocked; clean ones are forwarded to your package manager.\",\n )\n .argument(\"<args...>\", \"Packages to add (e.g. next vitest@1) : PM flags after the first package are passed through\")\n .option(\n \"--fail-on <level>\",\n `Block install when a finding meets this severity (${FAIL_ON_VALUES.join(\"|\")})`,\n parseFailOn,\n \"high\" as FailOnLevel,\n )\n .option(\n \"--pm <name>\",\n `Force a package manager (${PM_VALUES.join(\"|\")}). Auto-detected by default.`,\n parsePm,\n )\n .option(\n \"--allow-vulnerable\",\n \"Install even if vulnerabilities are found (still prints findings).\",\n )\n .passThroughOptions()\n .action(async (args: string[], opts: AddCliOptions) => {\n await executeAdd(args, opts);\n });\n\nprogram\n .command(\"install\")\n .alias(\"i\")\n .description(\n \"Run the project's package manager install. With package args, behaves like `add` (gates on vulnerabilities). With none, forwards directly.\",\n )\n .argument(\"[args...]\", \"Optional packages to add\")\n .option(\n \"--fail-on <level>\",\n `Block install when a finding meets this severity (${FAIL_ON_VALUES.join(\"|\")})`,\n parseFailOn,\n \"high\" as FailOnLevel,\n )\n .option(\n \"--pm <name>\",\n `Force a package manager (${PM_VALUES.join(\"|\")})`,\n parsePm,\n )\n .option(\"--allow-vulnerable\", \"Install even if vulnerabilities are found.\")\n .passThroughOptions()\n .action(async (args: string[], opts: AddCliOptions) => {\n if (args.length === 0) {\n // Bare install: pure passthrough.\n const pm = detectPackageManager({ override: opts.pm });\n const command = buildInstallCommand(pm, []);\n process.stdout.write(\n kleur.gray(`> ${command.bin} ${command.args.join(\" \")}\\n`),\n );\n try {\n const code = await runPackageManager(command);\n process.exit(code);\n } catch (err) {\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n }\n await executeAdd(args, opts);\n });\n\nprogram\n .command(\"remove\")\n .alias(\"uninstall\")\n .description(\n \"Remove packages by delegating to the project's package manager (no scan).\",\n )\n .argument(\"<args...>\", \"Packages to remove\")\n .option(\n \"--pm <name>\",\n `Force a package manager (${PM_VALUES.join(\"|\")})`,\n parsePm,\n )\n .passThroughOptions()\n .action(async (args: string[], opts: { pm?: PackageManager }) => {\n const pm = detectPackageManager({ override: opts.pm });\n const { specs, flags } = splitArgs(args);\n const command = buildRemoveCommand(pm, specs, flags);\n process.stdout.write(\n kleur.gray(`> ${command.bin} ${command.args.join(\" \")}\\n`),\n );\n try {\n const code = await runPackageManager(command);\n process.exit(code);\n } catch (err) {\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n });\n\ninterface ScanCliOptions {\n lockfile?: string;\n format: Format;\n failOn: FailOnLevel;\n prod?: boolean;\n includeDev?: boolean;\n cache?: boolean;\n details?: boolean;\n summary?: boolean;\n}\n\ntype InspectCliOptions = Omit<ScanCliOptions, \"failOn\">;\n\ninterface AddCliOptions {\n failOn: FailOnLevel;\n pm?: PackageManager;\n allowVulnerable?: boolean;\n}\n\nasync function runScanCommand(\n path: string,\n opts: ScanCliOptions,\n { gate }: { gate: boolean },\n): Promise<void> {\n if (opts.prod && opts.includeDev) {\n printErr(\"Cannot combine --prod and --include-dev. Choose one.\");\n process.exit(EXIT.invalidInput);\n }\n if (opts.details && opts.summary) {\n printErr(\"Cannot combine --details and --summary. Choose one.\");\n process.exit(EXIT.invalidInput);\n }\n\n try {\n const result = await scanProject({\n cwd: path,\n lockfile: opts.lockfile,\n includeDev: opts.includeDev,\n prodOnly: opts.prod,\n cache: opts.cache,\n });\n\n if (opts.format === \"json\") {\n process.stdout.write(`${reportJson(result)}\\n`);\n } else {\n const view = opts.summary\n ? \"summary\"\n : opts.details\n ? \"details\"\n : \"grouped\";\n const brand = process.stdout.isTTY === true;\n process.stdout.write(`${reportTable(result, { view, brand })}\\n`);\n }\n\n if (result.errors.length > 0) {\n process.exit(EXIT.operational);\n }\n\n if (!gate) {\n if (opts.format !== \"json\" && result.findings.length > 0) {\n process.stdout.write(\n `${kleur.gray(\n \"ℹ inspect mode: exiting 0 regardless of findings. Run `trawly scan` to gate CI.\",\n )}\\n`,\n );\n }\n process.exit(EXIT.ok);\n }\n\n if (meetsThreshold(result.findings, opts.failOn)) {\n if (opts.format !== \"json\") {\n process.stderr.write(\n `${kleur.red(\n `× Failing because at least one finding meets --fail-on=${opts.failOn}.`,\n )}\\n${kleur.gray(\n \" Run `trawly inspect` to log without exiting non-zero, or `trawly scan --fail-on=none` to disable the gate.\",\n )}\\n`,\n );\n }\n process.exit(EXIT.findings);\n }\n process.exit(EXIT.ok);\n } catch (err) {\n if (err instanceof ScanInputError) {\n printErr(err.message);\n process.exit(EXIT.invalidInput);\n }\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n}\n\nasync function executeAdd(args: string[], opts: AddCliOptions): Promise<void> {\n try {\n const result = await runAdd(args, {\n failOn: opts.failOn,\n pm: opts.pm,\n allowVulnerable: opts.allowVulnerable,\n });\n process.stdout.write(reportAdd(result));\n\n if (result.errored.length > 0) process.exit(EXIT.operational);\n if (result.pmExitCode !== undefined && result.pmExitCode !== 0) {\n process.exit(result.pmExitCode);\n }\n if (result.blocked.length > 0) process.exit(EXIT.findings);\n process.exit(EXIT.ok);\n } catch (err) {\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n}\n\nfunction splitArgs(args: string[]): { specs: string[]; flags: string[] } {\n const specs: string[] = [];\n const flags: string[] = [];\n for (const a of args) {\n if (a.startsWith(\"-\")) flags.push(a);\n else specs.push(a);\n }\n return { specs, flags };\n}\n\nfunction printErr(msg: string): void {\n process.stderr.write(`${kleur.red(msg)}\\n`);\n}\n\nawait program.parseAsync(process.argv);\n","import kleur from \"kleur\";\nimport { queryOsv } from \"../sources/osv.js\";\nimport { compareFindings, summarize } from \"../scanner.js\";\nimport { SEVERITY_RANK } from \"../types.js\";\nimport type { Finding, PackageInstance, Severity } from \"../types.js\";\nimport {\n buildAddCommand,\n detectPackageManager,\n type PackageManager,\n} from \"../installer/pm-detect.js\";\nimport { runPackageManager } from \"../installer/runner.js\";\nimport {\n parseSpec,\n partitionArgs,\n type ParsedSpec,\n type UnsupportedReason,\n} from \"../installer/spec-parser.js\";\nimport {\n resolveVersion,\n VersionResolveError,\n type ResolvedVersion,\n} from \"../installer/version-resolver.js\";\n\nexport interface AddOptions {\n cwd?: string;\n pm?: PackageManager;\n failOn: Severity | \"none\";\n allowVulnerable?: boolean;\n fetchImpl?: typeof fetch;\n /** Test seam: replace the real spawn with a stub. */\n runner?: typeof runPackageManager;\n}\n\nexport interface AddResult {\n /** Specs we sent to the package manager. */\n installed: ResolvedSpec[];\n /** Specs we refused to install. */\n blocked: BlockedSpec[];\n /** Specs we couldn't analyze (git, file, url, alias). */\n skipped: SkippedSpec[];\n /** Specs that failed registry resolution. */\n errored: ErroredSpec[];\n /** All findings collected, sorted. */\n findings: Finding[];\n /** Exit code from the PM, or undefined if we never ran it. */\n pmExitCode?: number;\n}\n\ninterface ResolvedSpec {\n spec: ParsedSpec;\n resolved: ResolvedVersion;\n findings: Finding[];\n}\n\ninterface BlockedSpec extends ResolvedSpec {\n reason: \"vulnerable\";\n}\n\ninterface SkippedSpec {\n spec: ParsedSpec;\n reason: UnsupportedReason;\n}\n\ninterface ErroredSpec {\n spec: ParsedSpec;\n message: string;\n}\n\nexport async function runAdd(\n args: string[],\n options: AddOptions,\n): Promise<AddResult> {\n const { specs, flags } = partitionArgs(args);\n\n const skipped: SkippedSpec[] = [];\n const resolvable: ParsedSpec[] = [];\n for (const spec of specs) {\n if (spec.unsupported) {\n skipped.push({ spec, reason: spec.unsupported });\n } else {\n resolvable.push(spec);\n }\n }\n\n const resolved: ResolvedSpec[] = [];\n const errored: ErroredSpec[] = [];\n await Promise.all(\n resolvable.map(async (spec) => {\n try {\n const r = await resolveVersion(spec.name, spec.requested, {\n fetchImpl: options.fetchImpl,\n });\n resolved.push({ spec, resolved: r, findings: [] });\n } catch (err) {\n const message =\n err instanceof VersionResolveError\n ? err.message\n : `Registry error: ${(err as Error).message}`;\n errored.push({ spec, message });\n }\n }),\n );\n\n let findings: Finding[] = [];\n if (resolved.length > 0) {\n const instances: PackageInstance[] = resolved.map((r) => ({\n name: r.spec.name,\n version: r.resolved.version,\n ecosystem: \"npm\",\n path: r.spec.raw,\n direct: true,\n dev: false,\n optional: false,\n }));\n try {\n findings = await queryOsv(instances, { fetchImpl: options.fetchImpl });\n } catch (err) {\n // If OSV is unreachable we cannot make a safe call; treat as a hard error\n // for every resolvable spec rather than silently letting installs through.\n const message = `OSV query failed: ${(err as Error).message}`;\n for (const r of resolved) errored.push({ spec: r.spec, message });\n resolved.length = 0;\n }\n }\n\n for (const f of findings) {\n const owner = resolved.find(\n (r) => r.spec.name === f.packageName && r.resolved.version === f.installedVersion,\n );\n if (owner) owner.findings.push(f);\n }\n\n const blocked: BlockedSpec[] = [];\n const installed: ResolvedSpec[] = [];\n for (const r of resolved) {\n if (shouldBlock(r.findings, options)) {\n blocked.push({ ...r, reason: \"vulnerable\" });\n } else {\n installed.push(r);\n }\n }\n\n findings.sort(compareFindings);\n\n let pmExitCode: number | undefined;\n if (installed.length > 0) {\n const pm = detectPackageManager({ override: options.pm, cwd: options.cwd });\n const cmd = buildAddCommand(\n pm,\n installed.map((r) => r.spec.raw),\n flags,\n );\n process.stdout.write(\n kleur.gray(`> ${cmd.bin} ${cmd.args.join(\" \")}\\n`),\n );\n const runner = options.runner ?? runPackageManager;\n pmExitCode = await runner(cmd, { cwd: options.cwd });\n }\n\n return { installed, blocked, skipped, errored, findings, pmExitCode };\n}\n\nexport function reportAdd(result: AddResult): string {\n const lines: string[] = [];\n\n if (result.skipped.length > 0) {\n for (const s of result.skipped) {\n lines.push(\n kleur.yellow(\n `~ Skipped ${s.spec.raw}: ${describeUnsupported(s.reason)} (cannot scan; not forwarded to install)`,\n ),\n );\n }\n }\n\n if (result.errored.length > 0) {\n for (const e of result.errored) {\n lines.push(kleur.red(`! ${e.spec.raw}: ${e.message}`));\n }\n }\n\n if (result.blocked.length > 0) {\n for (const b of result.blocked) {\n const sev = summarize(b.findings);\n const counts = describeSeverityCounts(sev);\n lines.push(\n kleur.red(\n `✗ Blocked ${b.spec.name}@${b.resolved.version}: ${counts}`,\n ),\n );\n if (b.resolved.source === \"fallback-latest\") {\n lines.push(\n kleur.gray(\n ` (scanned latest because we don't resolve semver ranges yet; you asked for \"${b.resolved.requested}\")`,\n ),\n );\n }\n for (const f of b.findings) {\n lines.push(\n ` - [${colorSeverity(f.severity)}] ${f.id} : ${f.summary}`,\n );\n if (f.fixedVersions.length > 0) {\n lines.push(kleur.gray(` fixed in: ${f.fixedVersions.join(\", \")}`));\n }\n if (f.url) lines.push(kleur.gray(` ${f.url}`));\n }\n }\n }\n\n if (result.installed.length > 0) {\n const names = result.installed\n .map((r) => `${r.spec.name}@${r.resolved.version}`)\n .join(\", \");\n lines.push(kleur.green(`✓ Installing: ${names}`));\n } else if (result.blocked.length > 0) {\n lines.push(\n kleur.red(\"Nothing installed : all requested packages were blocked.\"),\n );\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction shouldBlock(findings: Finding[], options: AddOptions): boolean {\n if (options.allowVulnerable) return false;\n if (options.failOn === \"none\") return false;\n const threshold = SEVERITY_RANK[options.failOn];\n return findings.some((f) => SEVERITY_RANK[f.severity] >= threshold);\n}\n\nfunction describeUnsupported(reason: UnsupportedReason): string {\n switch (reason) {\n case \"git\":\n return \"git specs cannot be scanned against OSV\";\n case \"url\":\n return \"URL specs cannot be scanned against OSV\";\n case \"file\":\n return \"local file specs cannot be scanned against OSV\";\n case \"alias\":\n return \"npm aliases are not supported in v1\";\n case \"workspace\":\n return \"workspace protocol specs are not scanned\";\n case \"invalid\":\n return \"could not parse spec\";\n }\n}\n\nfunction describeSeverityCounts(summary: Record<Severity, number>): string {\n const parts: string[] = [];\n for (const sev of [\"critical\", \"high\", \"moderate\", \"low\", \"unknown\"] as Severity[]) {\n if (summary[sev] > 0) parts.push(`${summary[sev]} ${sev}`);\n }\n return parts.length === 0 ? \"no advisories\" : `${parts.join(\", \")} advisor${total(summary) === 1 ? \"y\" : \"ies\"}`;\n}\n\nfunction total(summary: Record<Severity, number>): number {\n return Object.values(summary).reduce((a, b) => a + b, 0);\n}\n\nfunction colorSeverity(sev: Severity): string {\n switch (sev) {\n case \"critical\":\n return kleur.bold().red(sev);\n case \"high\":\n return kleur.red(sev);\n case \"moderate\":\n return kleur.yellow(sev);\n case \"low\":\n return kleur.cyan(sev);\n case \"unknown\":\n return kleur.gray(sev);\n }\n}\n\n// Re-exports so tests can poke at the parsed spec type.\nexport { parseSpec };\n","import type { Finding, PackageInstance, Severity } from \"../types.js\";\n\nconst OSV_QUERYBATCH_URL = \"https://api.osv.dev/v1/querybatch\";\nconst OSV_VULN_URL = \"https://api.osv.dev/v1/vulns\";\nconst QUERY_CHUNK_SIZE = 500;\nconst REQUEST_TIMEOUT_MS = 15_000;\nconst MAX_RETRIES = 2;\n\ninterface OsvQueryBatchResponse {\n results: Array<{ vulns?: Array<{ id: string; modified?: string }> }>;\n}\n\ninterface OsvSeverity {\n type: string;\n score: string;\n}\n\ninterface OsvAffectedRange {\n type: string;\n events: Array<{ introduced?: string; fixed?: string; last_affected?: string }>;\n}\n\ninterface OsvAffectedPackage {\n package?: { ecosystem?: string; name?: string };\n ranges?: OsvAffectedRange[];\n versions?: string[];\n}\n\ninterface OsvVulnDetail {\n id: string;\n summary?: string;\n details?: string;\n references?: Array<{ type?: string; url?: string }>;\n severity?: OsvSeverity[];\n database_specific?: { severity?: string };\n affected?: OsvAffectedPackage[];\n}\n\nexport interface OsvQueryDeps {\n fetchImpl?: typeof fetch;\n}\n\ninterface UniquePackage {\n name: string;\n version: string;\n}\n\n/**\n * Build the deduplicated list of unique name@version pairs to query OSV with.\n */\nexport function dedupeForQuery(\n packages: PackageInstance[],\n): UniquePackage[] {\n const seen = new Set<string>();\n const out: UniquePackage[] = [];\n for (const pkg of packages) {\n const key = `${pkg.name}@${pkg.version}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push({ name: pkg.name, version: pkg.version });\n }\n return out;\n}\n\n/**\n * Query OSV for the given installed packages and return one Finding per\n * (advisory, affected package instance) pair.\n */\nexport async function queryOsv(\n packages: PackageInstance[],\n deps: OsvQueryDeps = {},\n): Promise<Finding[]> {\n const fetchImpl = deps.fetchImpl ?? fetch;\n const unique = dedupeForQuery(packages);\n if (unique.length === 0) return [];\n\n const idsByPackage = new Map<string, Set<string>>();\n for (const chunk of chunked(unique, QUERY_CHUNK_SIZE)) {\n const body = {\n queries: chunk.map((q) => ({\n package: { ecosystem: \"npm\", name: q.name },\n version: q.version,\n })),\n };\n const res = await postJson<OsvQueryBatchResponse>(\n fetchImpl,\n OSV_QUERYBATCH_URL,\n body,\n );\n res.results.forEach((result, i) => {\n const q = chunk[i];\n if (!q) return;\n const key = `${q.name}@${q.version}`;\n if (!result.vulns || result.vulns.length === 0) return;\n const ids = idsByPackage.get(key) ?? new Set<string>();\n for (const v of result.vulns) ids.add(v.id);\n idsByPackage.set(key, ids);\n });\n }\n\n const allIds = new Set<string>();\n for (const ids of idsByPackage.values()) {\n for (const id of ids) allIds.add(id);\n }\n\n const detailsById = new Map<string, OsvVulnDetail>();\n for (const id of allIds) {\n try {\n const detail = await getJson<OsvVulnDetail>(\n fetchImpl,\n `${OSV_VULN_URL}/${encodeURIComponent(id)}`,\n );\n detailsById.set(id, detail);\n } catch {\n // Skip missing/broken records; we still have the id reported below.\n }\n }\n\n const findings: Finding[] = [];\n for (const pkg of packages) {\n const key = `${pkg.name}@${pkg.version}`;\n const ids = idsByPackage.get(key);\n if (!ids) continue;\n for (const id of ids) {\n const detail = detailsById.get(id);\n findings.push(buildFinding(pkg, id, detail));\n }\n }\n return findings;\n}\n\nfunction buildFinding(\n pkg: PackageInstance,\n id: string,\n detail: OsvVulnDetail | undefined,\n): Finding {\n const severity = detail ? parseSeverity(detail) : \"unknown\";\n const summary = detail?.summary ?? detail?.details ?? id;\n return {\n id,\n source: \"osv\",\n type: \"vulnerability\",\n severity,\n packageName: pkg.name,\n installedVersion: pkg.version,\n summary: truncate(summary, 240),\n url: pickAdvisoryUrl(detail) ?? `https://osv.dev/vulnerability/${id}`,\n fixedVersions: detail ? collectFixedVersions(detail, pkg.name) : [],\n affectedPaths: [pkg.path],\n };\n}\n\nexport function parseSeverity(detail: OsvVulnDetail): Severity {\n // GHSA records expose a normalized severity in database_specific.severity.\n const dbSpecific = detail.database_specific?.severity?.toLowerCase();\n if (\n dbSpecific === \"critical\" ||\n dbSpecific === \"high\" ||\n dbSpecific === \"moderate\" ||\n dbSpecific === \"low\"\n ) {\n return dbSpecific;\n }\n if (dbSpecific === \"medium\") return \"moderate\";\n\n const cvss = detail.severity?.find((s) => s.type?.startsWith(\"CVSS_\"));\n if (cvss) {\n const score = parseCvssScore(cvss.score);\n if (score === undefined) return \"unknown\";\n if (score >= 9.0) return \"critical\";\n if (score >= 7.0) return \"high\";\n if (score >= 4.0) return \"moderate\";\n if (score > 0) return \"low\";\n }\n return \"unknown\";\n}\n\nfunction parseCvssScore(vector: string): number | undefined {\n const direct = Number.parseFloat(vector);\n if (!Number.isNaN(direct) && vector.trim() !== \"\") return direct;\n // Some entries store the full CVSS vector string; we don't compute it here.\n return undefined;\n}\n\nfunction pickAdvisoryUrl(detail: OsvVulnDetail | undefined): string | undefined {\n if (!detail?.references) return undefined;\n const advisory = detail.references.find((r) => r.type === \"ADVISORY\");\n return advisory?.url ?? detail.references[0]?.url;\n}\n\nexport function collectFixedVersions(\n detail: OsvVulnDetail,\n packageName: string,\n): string[] {\n const out = new Set<string>();\n for (const aff of detail.affected ?? []) {\n if (aff.package?.name && aff.package.name !== packageName) continue;\n for (const range of aff.ranges ?? []) {\n for (const event of range.events ?? []) {\n if (event.fixed) out.add(event.fixed);\n }\n }\n }\n return [...out];\n}\n\nfunction* chunked<T>(items: T[], size: number): Generator<T[]> {\n for (let i = 0; i < items.length; i += size) {\n yield items.slice(i, i + size);\n }\n}\n\nasync function postJson<T>(\n fetchImpl: typeof fetch,\n url: string,\n body: unknown,\n): Promise<T> {\n return withRetry(async () => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n const res = await fetchImpl(url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n throw new HttpError(`OSV ${res.status}: ${res.statusText}`, res.status);\n }\n return (await res.json()) as T;\n } finally {\n clearTimeout(timer);\n }\n });\n}\n\nasync function getJson<T>(fetchImpl: typeof fetch, url: string): Promise<T> {\n return withRetry(async () => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n const res = await fetchImpl(url, { signal: controller.signal });\n if (!res.ok) {\n throw new HttpError(`OSV ${res.status}: ${res.statusText}`, res.status);\n }\n return (await res.json()) as T;\n } finally {\n clearTimeout(timer);\n }\n });\n}\n\nclass HttpError extends Error {\n constructor(message: string, public readonly status: number) {\n super(message);\n }\n}\n\nasync function withRetry<T>(fn: () => Promise<T>): Promise<T> {\n let lastErr: unknown;\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastErr = err;\n if (!isRetryable(err) || attempt === MAX_RETRIES) break;\n await new Promise((r) => setTimeout(r, 250 * 2 ** attempt));\n }\n }\n throw lastErr;\n}\n\nfunction isRetryable(err: unknown): boolean {\n if (err instanceof HttpError) return err.status >= 500;\n // AbortError (timeout) and network errors are retryable.\n return true;\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return `${s.slice(0, max - 1)}…`;\n}\n","import { existsSync, statSync } from \"node:fs\";\nimport { resolve, join } from \"node:path\";\nimport { parseNpmPackageLock } from \"./extractors/npm-package-lock.js\";\nimport { queryOsv } from \"./sources/osv.js\";\nimport { SEVERITY_RANK } from \"./types.js\";\nimport type {\n Finding,\n PackageInstance,\n ScanError,\n ScanLockfileOptions,\n ScanProjectOptions,\n ScanResult,\n Severity,\n} from \"./types.js\";\n\nexport async function scanProject(\n options: ScanProjectOptions = {},\n): Promise<ScanResult> {\n const cwd = resolve(options.cwd ?? process.cwd());\n const lockfilePath = options.lockfile\n ? resolve(cwd, options.lockfile)\n : detectLockfile(cwd);\n\n if (!lockfilePath) {\n throw new ScanInputError(\n `No npm lockfile found in ${cwd}. Pass --lockfile or run in a directory with package-lock.json.`,\n );\n }\n\n return scanLockfile({\n lockfilePath,\n includeDev: options.includeDev,\n prodOnly: options.prodOnly,\n fetchImpl: options.fetchImpl,\n });\n}\n\nexport async function scanLockfile(\n options: ScanLockfileOptions,\n): Promise<ScanResult> {\n const { lockfilePath } = options;\n if (!existsSync(lockfilePath)) {\n throw new ScanInputError(`Lockfile does not exist: ${lockfilePath}`);\n }\n const stat = statSync(lockfilePath);\n if (!stat.isFile()) {\n throw new ScanInputError(`Lockfile path is not a file: ${lockfilePath}`);\n }\n\n const allInstances = parseNpmPackageLock(lockfilePath);\n const instances = filterInstances(allInstances, options);\n const errors: ScanError[] = [];\n\n let findings: Finding[] = [];\n try {\n findings = await queryOsv(instances, { fetchImpl: options.fetchImpl });\n } catch (err) {\n errors.push({\n message: \"Failed to query OSV advisory database\",\n cause: (err as Error).message,\n });\n }\n\n findings.sort(compareFindings);\n\n return {\n scannedAt: new Date().toISOString(),\n packagesScanned: instances.length,\n findings,\n summary: summarize(findings),\n errors,\n };\n}\n\nexport class ScanInputError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ScanInputError\";\n }\n}\n\nfunction detectLockfile(cwd: string): string | undefined {\n const candidate = join(cwd, \"package-lock.json\");\n return existsSync(candidate) ? candidate : undefined;\n}\n\nfunction filterInstances(\n instances: PackageInstance[],\n options: { includeDev?: boolean; prodOnly?: boolean },\n): PackageInstance[] {\n const includeDev = options.prodOnly ? false : options.includeDev !== false;\n if (includeDev) return instances;\n return instances.filter((p) => !p.dev);\n}\n\nexport function compareFindings(a: Finding, b: Finding): number {\n const sev = SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity];\n if (sev !== 0) return sev;\n if (a.packageName !== b.packageName) {\n return a.packageName.localeCompare(b.packageName);\n }\n if (a.installedVersion !== b.installedVersion) {\n return a.installedVersion.localeCompare(b.installedVersion);\n }\n return a.id.localeCompare(b.id);\n}\n\nexport function summarize(findings: Finding[]): Record<Severity, number> {\n const summary: Record<Severity, number> = {\n critical: 0,\n high: 0,\n moderate: 0,\n low: 0,\n unknown: 0,\n };\n for (const f of findings) summary[f.severity]++;\n return summary;\n}\n\n/**\n * Returns true when any finding meets or exceeds the given severity threshold.\n * \"none\" means never fail.\n */\nexport function meetsThreshold(\n findings: Finding[],\n threshold: Severity | \"none\",\n): boolean {\n if (threshold === \"none\") return false;\n const min = SEVERITY_RANK[threshold];\n return findings.some((f) => SEVERITY_RANK[f.severity] >= min);\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { PackageInstance } from \"../types.js\";\n\ninterface NpmLockEntry {\n version?: string;\n resolved?: string;\n integrity?: string;\n dev?: boolean;\n devOptional?: boolean;\n optional?: boolean;\n peer?: boolean;\n link?: boolean;\n // Present on the root (\"\") entry only.\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\ninterface NpmLockfile {\n name?: string;\n lockfileVersion?: number;\n packages?: Record<string, NpmLockEntry>;\n}\n\n/**\n * Parse an npm `package-lock.json` (v2 or v3) and return one\n * PackageInstance per node in the `packages` map.\n *\n * The empty-string key represents the root project and is skipped.\n */\nexport function parseNpmPackageLock(filePath: string): PackageInstance[] {\n const absolute = resolve(filePath);\n const raw = readFileSync(absolute, \"utf8\");\n let parsed: NpmLockfile;\n try {\n parsed = JSON.parse(raw) as NpmLockfile;\n } catch (err) {\n throw new Error(\n `Failed to parse ${absolute}: ${(err as Error).message}`,\n );\n }\n\n if (parsed.lockfileVersion !== 2 && parsed.lockfileVersion !== 3) {\n throw new Error(\n `Unsupported npm lockfileVersion ${String(\n parsed.lockfileVersion,\n )} in ${absolute}. Only v2 and v3 are supported.`,\n );\n }\n\n const packages = parsed.packages;\n if (!packages || typeof packages !== \"object\") {\n throw new Error(\n `Lockfile ${absolute} has no \"packages\" map; cannot extract installed versions.`,\n );\n }\n\n const directDeps = collectDirectDependencyNames(packages[\"\"] ?? {});\n const instances: PackageInstance[] = [];\n\n for (const [path, entry] of Object.entries(packages)) {\n if (path === \"\") continue;\n if (entry.link) continue; // workspace symlink, not a real install\n const name = packagePathToName(path);\n if (!name) continue;\n if (!entry.version) continue;\n\n instances.push({\n name,\n version: entry.version,\n ecosystem: \"npm\",\n path,\n direct: directDeps.has(name) && isTopLevelInstance(path),\n dev: Boolean(entry.dev || entry.devOptional),\n optional: Boolean(entry.optional || entry.devOptional),\n resolved: entry.resolved,\n integrity: entry.integrity,\n });\n }\n\n return instances;\n}\n\nfunction collectDirectDependencyNames(rootEntry: NpmLockEntry): Set<string> {\n const names = new Set<string>();\n for (const key of [\n \"dependencies\",\n \"devDependencies\",\n \"optionalDependencies\",\n \"peerDependencies\",\n ] as const) {\n const block = rootEntry[key];\n if (!block) continue;\n for (const name of Object.keys(block)) names.add(name);\n }\n return names;\n}\n\n/**\n * \"node_modules/foo\" -> \"foo\"\n * \"node_modules/@scope/bar\" -> \"@scope/bar\"\n * \"node_modules/foo/node_modules/bar\" -> \"bar\"\n */\nexport function packagePathToName(path: string): string | null {\n const marker = \"node_modules/\";\n const idx = path.lastIndexOf(marker);\n if (idx === -1) return null;\n const tail = path.slice(idx + marker.length);\n if (!tail) return null;\n if (tail.startsWith(\"@\")) {\n const firstSlash = tail.indexOf(\"/\");\n if (firstSlash === -1) return null;\n const secondSlash = tail.indexOf(\"/\", firstSlash + 1);\n return secondSlash === -1 ? tail : tail.slice(0, secondSlash);\n }\n const next = tail.indexOf(\"/\");\n return next === -1 ? tail : tail.slice(0, next);\n}\n\n/** A direct-install path has exactly one `node_modules/` segment. */\nfunction isTopLevelInstance(path: string): boolean {\n const first = path.indexOf(\"node_modules/\");\n if (first === -1) return false;\n return path.indexOf(\"node_modules/\", first + 1) === -1;\n}\n","export type Severity = \"critical\" | \"high\" | \"moderate\" | \"low\" | \"unknown\";\n\nexport type Ecosystem = \"npm\";\n\nexport type FindingType =\n | \"vulnerability\"\n | \"malware\"\n | \"risk-signal\"\n | \"integrity\";\n\nexport const SEVERITY_RANK: Record<Severity, number> = {\n critical: 4,\n high: 3,\n moderate: 2,\n low: 1,\n unknown: 0,\n};\n\nexport interface PackageInstance {\n name: string;\n version: string;\n ecosystem: Ecosystem;\n /** Path within the lockfile's `packages` map (e.g. \"node_modules/foo\"). */\n path: string;\n direct: boolean;\n dev: boolean;\n optional: boolean;\n resolved?: string;\n integrity?: string;\n}\n\nexport interface Finding {\n id: string;\n source: \"osv\";\n type: FindingType;\n severity: Severity;\n packageName: string;\n installedVersion: string;\n summary: string;\n url?: string;\n fixedVersions: string[];\n affectedPaths: string[];\n}\n\nexport interface ScanError {\n message: string;\n cause?: string;\n}\n\nexport interface ScanResult {\n scannedAt: string;\n packagesScanned: number;\n findings: Finding[];\n summary: Record<Severity, number>;\n errors: ScanError[];\n}\n\nexport interface ScanProjectOptions {\n cwd?: string;\n lockfile?: string;\n includeDev?: boolean;\n prodOnly?: boolean;\n cache?: boolean;\n fetchImpl?: typeof fetch;\n}\n\nexport interface ScanLockfileOptions {\n lockfilePath: string;\n includeDev?: boolean;\n prodOnly?: boolean;\n fetchImpl?: typeof fetch;\n}\n\nexport type FailOnLevel = Severity | \"none\";\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nexport interface PmCommand {\n /** Binary to spawn, e.g. \"pnpm\". */\n bin: string;\n /** Argv to spawn it with. */\n args: string[];\n}\n\nexport interface DetectOptions {\n /** Override detection. */\n override?: PackageManager;\n /** Project directory. Defaults to cwd. */\n cwd?: string;\n}\n\nconst LOCKFILES: Array<{ file: string; pm: PackageManager }> = [\n { file: \"pnpm-lock.yaml\", pm: \"pnpm\" },\n { file: \"yarn.lock\", pm: \"yarn\" },\n { file: \"bun.lockb\", pm: \"bun\" },\n { file: \"bun.lock\", pm: \"bun\" },\n { file: \"package-lock.json\", pm: \"npm\" },\n { file: \"npm-shrinkwrap.json\", pm: \"npm\" },\n];\n\nexport function detectPackageManager(opts: DetectOptions = {}): PackageManager {\n if (opts.override) return opts.override;\n const cwd = opts.cwd ?? process.cwd();\n\n const fromField = readPackageManagerField(cwd);\n if (fromField) return fromField;\n\n for (const { file, pm } of LOCKFILES) {\n if (existsSync(join(cwd, file))) return pm;\n }\n return \"npm\";\n}\n\nfunction readPackageManagerField(cwd: string): PackageManager | undefined {\n const pkgPath = join(cwd, \"package.json\");\n if (!existsSync(pkgPath)) return undefined;\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as {\n packageManager?: string;\n };\n if (typeof pkg.packageManager !== \"string\") return undefined;\n const name = pkg.packageManager.split(\"@\")[0];\n if (name === \"npm\" || name === \"pnpm\" || name === \"yarn\" || name === \"bun\") {\n return name;\n }\n } catch {\n // Malformed package.json : fall back to lockfile detection.\n }\n return undefined;\n}\n\n/**\n * Build the argv to add packages with the chosen package manager.\n * `flags` are user-supplied PM flags (e.g. -D, --save-exact) preserved as-is.\n */\nexport function buildAddCommand(\n pm: PackageManager,\n packages: string[],\n flags: string[],\n): PmCommand {\n switch (pm) {\n case \"npm\":\n return { bin: \"npm\", args: [\"install\", ...flags, ...packages] };\n case \"pnpm\":\n return { bin: \"pnpm\", args: [\"add\", ...flags, ...packages] };\n case \"yarn\":\n return { bin: \"yarn\", args: [\"add\", ...flags, ...packages] };\n case \"bun\":\n return { bin: \"bun\", args: [\"add\", ...flags, ...packages] };\n }\n}\n\nexport function buildInstallCommand(\n pm: PackageManager,\n flags: string[],\n): PmCommand {\n return { bin: pm, args: [\"install\", ...flags] };\n}\n\nexport function buildRemoveCommand(\n pm: PackageManager,\n packages: string[],\n flags: string[],\n): PmCommand {\n switch (pm) {\n case \"npm\":\n return { bin: \"npm\", args: [\"uninstall\", ...flags, ...packages] };\n case \"pnpm\":\n return { bin: \"pnpm\", args: [\"remove\", ...flags, ...packages] };\n case \"yarn\":\n return { bin: \"yarn\", args: [\"remove\", ...flags, ...packages] };\n case \"bun\":\n return { bin: \"bun\", args: [\"remove\", ...flags, ...packages] };\n }\n}\n","import { spawn } from \"node:child_process\";\nimport type { PmCommand } from \"./pm-detect.js\";\n\nexport interface RunOptions {\n cwd?: string;\n}\n\n/**\n * Spawn the package manager with stdio inherited so the user sees the live\n * install output. Resolves with the PM's exit code.\n */\nexport function runPackageManager(\n cmd: PmCommand,\n opts: RunOptions = {},\n): Promise<number> {\n return new Promise((resolve, reject) => {\n const child = spawn(cmd.bin, cmd.args, {\n cwd: opts.cwd,\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => resolve(code ?? 0));\n });\n}\n","export interface ParsedSpec {\n /** Original argv token, preserved so we can hand it back to the package manager. */\n raw: string;\n /** Bare package name, e.g. \"next\" or \"@types/node\". */\n name: string;\n /**\n * Whatever followed the \"@\" separator: an exact version, a semver range,\n * or a dist-tag like \"latest\" / \"next\". Undefined when the user passed only\n * the package name.\n */\n requested?: string;\n /** Specs we cannot meaningfully scan (git, tarball, file, url, alias). */\n unsupported?: UnsupportedReason;\n}\n\nexport type UnsupportedReason =\n | \"git\"\n | \"url\"\n | \"file\"\n | \"alias\"\n | \"workspace\"\n | \"invalid\";\n\nconst URL_PROTOCOLS = [\"http:\", \"https:\", \"git:\", \"git+ssh:\", \"git+https:\", \"git+http:\"];\n\nexport function parseSpec(raw: string): ParsedSpec {\n const trimmed = raw.trim();\n if (trimmed === \"\") {\n return { raw, name: \"\", unsupported: \"invalid\" };\n }\n\n if (trimmed.startsWith(\"file:\")) return { raw, name: trimmed, unsupported: \"file\" };\n if (trimmed.startsWith(\"workspace:\")) {\n return { raw, name: trimmed, unsupported: \"workspace\" };\n }\n if (URL_PROTOCOLS.some((p) => trimmed.startsWith(p))) {\n const reason = trimmed.includes(\"git\") ? \"git\" : \"url\";\n return { raw, name: trimmed, unsupported: reason };\n }\n // npm aliases: \"alias@npm:real-pkg@1.0\". We can't reliably gate these in v1.\n if (/^[^@/].*@npm:/.test(trimmed) || /^@[^/]+\\/[^@]+@npm:/.test(trimmed)) {\n return { raw, name: trimmed, unsupported: \"alias\" };\n }\n\n // Scoped: \"@scope/name\" or \"@scope/name@version\".\n if (trimmed.startsWith(\"@\")) {\n const slash = trimmed.indexOf(\"/\");\n if (slash === -1) return { raw, name: trimmed, unsupported: \"invalid\" };\n const rest = trimmed.slice(slash + 1);\n const at = rest.indexOf(\"@\");\n if (at === -1) {\n return { raw, name: trimmed };\n }\n const subname = rest.slice(0, at);\n const requested = rest.slice(at + 1);\n if (subname === \"\" || requested === \"\") {\n return { raw, name: trimmed, unsupported: \"invalid\" };\n }\n return { raw, name: `${trimmed.slice(0, slash)}/${subname}`, requested };\n }\n\n const at = trimmed.indexOf(\"@\");\n if (at === -1) return { raw, name: trimmed };\n const name = trimmed.slice(0, at);\n const requested = trimmed.slice(at + 1);\n if (name === \"\" || requested === \"\") {\n return { raw, name: trimmed, unsupported: \"invalid\" };\n }\n return { raw, name, requested };\n}\n\n/**\n * Splits an argv list into recognized package specs and forwarded flags.\n * Anything starting with \"-\" is treated as a flag and preserved untouched.\n */\nexport function partitionArgs(args: string[]): {\n specs: ParsedSpec[];\n flags: string[];\n} {\n const specs: ParsedSpec[] = [];\n const flags: string[] = [];\n for (const arg of args) {\n if (arg.startsWith(\"-\")) {\n flags.push(arg);\n continue;\n }\n specs.push(parseSpec(arg));\n }\n return { specs, flags };\n}\n","const REGISTRY_URL = \"https://registry.npmjs.org\";\nconst REQUEST_TIMEOUT_MS = 15_000;\n\nexport interface ResolveDeps {\n fetchImpl?: typeof fetch;\n registryUrl?: string;\n}\n\nexport interface ResolvedVersion {\n /** Concrete version we'll hand to OSV. */\n version: string;\n /**\n * How we picked it: \"exact\" (user pinned), \"dist-tag\" (latest/next/etc),\n * or \"fallback-latest\" (we couldn't resolve a range so we scanned latest).\n */\n source: \"exact\" | \"dist-tag\" | \"fallback-latest\";\n /** Set when source !== \"exact\" : what the user asked for. */\n requested?: string;\n}\n\ninterface PackumentDistTags {\n latest?: string;\n [tag: string]: string | undefined;\n}\n\ninterface Packument {\n name?: string;\n \"dist-tags\"?: PackumentDistTags;\n versions?: Record<string, unknown>;\n}\n\nconst EXACT_VERSION_RE = /^\\d+\\.\\d+\\.\\d+(?:[-+][\\w.+-]+)?$/;\nconst RANGE_CHARS_RE = /[\\^~><=|\\s*x]/i;\n\n/**\n * Resolve a user-supplied spec to a concrete version we can query OSV with.\n *\n * Strategy (v1):\n * - no version requested → dist-tags.latest\n * - exact version (1.2.3) → use as-is, verified to exist\n * - dist-tag (latest/next/beta) → dist-tags[tag], or fall back to latest\n * - semver range (^1, >=2) → dist-tags.latest with source=\"fallback-latest\"\n *\n * The fallback case is a known limitation: the installed version may differ\n * from what we scanned. The orchestrator surfaces this in its report.\n */\nexport async function resolveVersion(\n name: string,\n requested: string | undefined,\n deps: ResolveDeps = {},\n): Promise<ResolvedVersion> {\n const fetchImpl = deps.fetchImpl ?? fetch;\n const registry = deps.registryUrl ?? REGISTRY_URL;\n const packument = await fetchPackument(fetchImpl, registry, name);\n\n const distTags = packument[\"dist-tags\"] ?? {};\n const latest = distTags.latest;\n\n if (!requested) {\n if (!latest) {\n throw new VersionResolveError(\n `Package ${name} has no \"latest\" dist-tag in the registry.`,\n );\n }\n return { version: latest, source: \"dist-tag\", requested: \"latest\" };\n }\n\n if (EXACT_VERSION_RE.test(requested)) {\n if (packument.versions && !packument.versions[requested]) {\n throw new VersionResolveError(\n `Version ${requested} of ${name} is not published.`,\n );\n }\n return { version: requested, source: \"exact\" };\n }\n\n if (!RANGE_CHARS_RE.test(requested) && distTags[requested]) {\n return {\n version: distTags[requested] as string,\n source: \"dist-tag\",\n requested,\n };\n }\n\n if (!latest) {\n throw new VersionResolveError(\n `Cannot resolve ${name}@${requested}: no \"latest\" dist-tag available to fall back on.`,\n );\n }\n return { version: latest, source: \"fallback-latest\", requested };\n}\n\nexport class VersionResolveError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"VersionResolveError\";\n }\n}\n\nasync function fetchPackument(\n fetchImpl: typeof fetch,\n registry: string,\n name: string,\n): Promise<Packument> {\n const url = `${registry.replace(/\\/$/, \"\")}/${encodePackageName(name)}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n const res = await fetchImpl(url, {\n signal: controller.signal,\n headers: { accept: \"application/json\" },\n });\n if (res.status === 404) {\n throw new VersionResolveError(`Package ${name} not found in registry.`);\n }\n if (!res.ok) {\n throw new VersionResolveError(\n `Registry ${res.status} for ${name}: ${res.statusText}`,\n );\n }\n return (await res.json()) as Packument;\n } finally {\n clearTimeout(timer);\n }\n}\n\nfunction encodePackageName(name: string): string {\n // Scoped names: \"@scope/name\" → \"@scope%2Fname\"\n if (name.startsWith(\"@\")) {\n const slash = name.indexOf(\"/\");\n if (slash !== -1) {\n return `${encodeURIComponent(name.slice(0, slash))}%2F${encodeURIComponent(name.slice(slash + 1))}`;\n }\n }\n return encodeURIComponent(name);\n}\n","import type { ScanResult } from \"../types.js\";\n\nexport function reportJson(result: ScanResult): string {\n return JSON.stringify(result, null, 2);\n}\n","import kleur from \"kleur\";\nimport {\n type Finding,\n type ScanResult,\n type Severity,\n SEVERITY_RANK,\n} from \"../types.js\";\nimport { renderBanner } from \"./banner.js\";\n\nexport type TableView = \"grouped\" | \"details\" | \"summary\";\n\nexport interface ReportTableOptions {\n /** @deprecated use `view` instead */\n details?: boolean;\n view?: TableView;\n /**\n * When true, renders a boxed `trawly` nameplate at the top in place of the\n * plain `trawly: …` header. CLI sets this only when stdout is a TTY so that\n * piped/CI output stays log-parser friendly.\n */\n brand?: boolean;\n}\n\nconst SEVERITY_COLOR: Record<Severity, (s: string) => string> = {\n critical: (s) => kleur.bold().red(s),\n high: (s) => kleur.red(s),\n moderate: (s) => kleur.yellow(s),\n low: (s) => kleur.cyan(s),\n unknown: (s) => kleur.gray(s),\n};\n\nconst SEVERITY_ORDER: Severity[] = [\n \"critical\",\n \"high\",\n \"moderate\",\n \"low\",\n \"unknown\",\n];\n\ninterface PackageGroup {\n packageName: string;\n installedVersion: string;\n topSeverity: Severity;\n counts: Record<Severity, number>;\n findings: Finding[];\n recommendedFix: string | null;\n}\n\nexport function reportTable(\n result: ScanResult,\n options: ReportTableOptions = {},\n): string {\n const view: TableView = options.view ?? (options.details ? \"details\" : \"grouped\");\n const lines: string[] = [];\n\n if (options.brand) {\n const { metricsLine, timestamp } = headerParts(result);\n lines.push(renderBanner({ metrics: metricsLine, timestamp }));\n } else {\n lines.push(kleur.bold(formatHeader(result)));\n }\n\n if (result.errors.length > 0) {\n for (const err of result.errors) {\n lines.push(\n kleur.red(`! ${err.message}${err.cause ? ` (${err.cause})` : \"\"}`),\n );\n }\n }\n\n if (result.findings.length === 0) {\n lines.push(kleur.green(\"✓ No known advisories found.\"));\n lines.push(\n kleur.gray(\n \" Note: this only checks known advisories. It cannot prove a package is safe.\",\n ),\n );\n return lines.join(\"\\n\");\n }\n\n if (view === \"summary\") {\n lines.push(formatSummary(result.summary));\n lines.push(reminder());\n return lines.join(\"\\n\");\n }\n\n lines.push(\"\");\n lines.push(formatSummary(result.summary));\n lines.push(\"\");\n\n if (view === \"details\") {\n lines.push(formatDetailRows(sortFindings(result.findings)));\n } else {\n const groups = groupByPackage(result.findings);\n lines.push(formatGroupedRows(groups));\n lines.push(\"\");\n lines.push(\n kleur.gray(\"Run `trawly scan --details` to see individual advisories.\"),\n );\n }\n\n lines.push(\"\");\n lines.push(reminder());\n return lines.join(\"\\n\");\n}\n\nfunction formatHeader(result: ScanResult): string {\n const { metricsLine, timestamp } = headerParts(result);\n return `trawly: ${metricsLine} (${timestamp})`;\n}\n\nfunction headerParts(result: ScanResult): {\n metricsLine: string;\n timestamp: string;\n} {\n const vulnerable = new Set(\n result.findings.map((f) => `${f.packageName}@${f.installedVersion}`),\n ).size;\n const advisories = result.findings.length;\n const metricsLine = [\n `${result.packagesScanned} packages`,\n `${vulnerable} vulnerable`,\n `${advisories} ${advisories === 1 ? \"advisory\" : \"advisories\"}`,\n ].join(\" · \");\n return { metricsLine, timestamp: result.scannedAt };\n}\n\nfunction formatSummary(summary: ScanResult[\"summary\"]): string {\n const parts: string[] = [];\n for (const sev of SEVERITY_ORDER) {\n const count = summary[sev];\n if (count === 0) continue;\n parts.push(SEVERITY_COLOR[sev](`${sev}: ${count}`));\n }\n if (parts.length === 0) return kleur.green(\"No findings.\");\n return `Findings : ${parts.join(\" \")}`;\n}\n\nfunction reminder(): string {\n return kleur.gray(\n \"Reminder: trawly reports known advisories only. Absence of findings is not proof of safety.\",\n );\n}\n\nfunction sortFindings(findings: Finding[]): Finding[] {\n return [...findings].sort((a, b) => {\n const sev = SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity];\n if (sev !== 0) return sev;\n const name = a.packageName.localeCompare(b.packageName);\n if (name !== 0) return name;\n return a.id.localeCompare(b.id);\n });\n}\n\nfunction groupByPackage(findings: Finding[]): PackageGroup[] {\n const map = new Map<string, PackageGroup>();\n for (const f of findings) {\n const key = `${f.packageName}@${f.installedVersion}`;\n let group = map.get(key);\n if (!group) {\n group = {\n packageName: f.packageName,\n installedVersion: f.installedVersion,\n topSeverity: f.severity,\n counts: { critical: 0, high: 0, moderate: 0, low: 0, unknown: 0 },\n findings: [],\n recommendedFix: null,\n };\n map.set(key, group);\n }\n group.findings.push(f);\n group.counts[f.severity] += 1;\n if (SEVERITY_RANK[f.severity] > SEVERITY_RANK[group.topSeverity]) {\n group.topSeverity = f.severity;\n }\n }\n\n for (const group of map.values()) {\n group.recommendedFix = pickRecommendedFix(group.findings);\n }\n\n return [...map.values()].sort((a, b) => {\n const sev = SEVERITY_RANK[b.topSeverity] - SEVERITY_RANK[a.topSeverity];\n if (sev !== 0) return sev;\n const totalA = a.findings.length;\n const totalB = b.findings.length;\n if (totalA !== totalB) return totalB - totalA;\n return a.packageName.localeCompare(b.packageName);\n });\n}\n\nfunction formatGroupedRows(groups: PackageGroup[]): string {\n const rows: string[][] = [\n [\"PACKAGE\", \"VERSION\", \"SEVERITY\", \"FIX\"],\n ];\n for (const g of groups) {\n rows.push([\n g.packageName,\n g.installedVersion,\n formatSeverityCounts(g.counts),\n g.recommendedFix ? `>=${g.recommendedFix}` : \":\",\n ]);\n }\n return renderTable(rows, (rowIdx, _row, cells) => {\n if (rowIdx === 0) return kleur.bold().underline(cells.join(\" \"));\n return cells.join(\" \");\n });\n}\n\nfunction formatDetailRows(findings: Finding[]): string {\n const rows: string[][] = [\n [\"SEV\", \"PACKAGE\", \"VERSION\", \"ID\", \"FIXED IN\", \"SUMMARY\"],\n ];\n for (const f of findings) {\n rows.push([\n f.severity,\n f.packageName,\n f.installedVersion,\n f.id,\n f.fixedVersions.length ? f.fixedVersions.join(\", \") : \":\",\n truncate(f.summary, 70),\n ]);\n }\n return renderTable(rows, (rowIdx, row, cells) => {\n if (rowIdx === 0) return kleur.bold().underline(cells.join(\" \"));\n const sev = row[0] as Severity;\n const colorize = SEVERITY_COLOR[sev] ?? ((s: string) => s);\n cells[0] = colorize(cells[0]!);\n return cells.join(\" \");\n });\n}\n\nfunction formatSeverityCounts(counts: Record<Severity, number>): string {\n const parts: string[] = [];\n for (const sev of SEVERITY_ORDER) {\n const n = counts[sev];\n if (n === 0) continue;\n parts.push(SEVERITY_COLOR[sev](`${n} ${sev}`));\n }\n return parts.join(\", \");\n}\n\nfunction renderTable(\n rows: string[][],\n format: (rowIdx: number, row: string[], cells: string[]) => string,\n): string {\n const widths = rows[0]!.map((_, col) =>\n Math.max(...rows.map((r) => visibleLength(r[col]!))),\n );\n return rows\n .map((row, i) => {\n const cells = row.map((cell, col) => padEndVisible(cell, widths[col]!));\n return format(i, row, cells);\n })\n .join(\"\\n\");\n}\n\n/**\n * Pick the highest semver-ish value across all fixedVersions in the group.\n * Picking the max guarantees the upgrade clears every known advisory; users\n * can drop into `--details` if they want to evaluate alternative fix lines\n * (e.g. staying on a previous major).\n */\nfunction pickRecommendedFix(findings: Finding[]): string | null {\n const candidates: string[] = [];\n for (const f of findings) {\n for (const v of f.fixedVersions) candidates.push(v);\n }\n if (candidates.length === 0) return null;\n const unique = [...new Set(candidates)];\n unique.sort(compareSemver);\n return unique[unique.length - 1] ?? null;\n}\n\nfunction compareSemver(a: string, b: string): number {\n const pa = parseSemverParts(a);\n const pb = parseSemverParts(b);\n for (let i = 0; i < 3; i++) {\n const diff = (pa[i] ?? 0) - (pb[i] ?? 0);\n if (diff !== 0) return diff;\n }\n return a.localeCompare(b);\n}\n\nfunction parseSemverParts(v: string): number[] {\n const m = v.match(/(\\d+)\\.(\\d+)\\.(\\d+)/);\n if (!m) return [0, 0, 0];\n return [Number(m[1]), Number(m[2]), Number(m[3])];\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return `${s.slice(0, max - 1)}…`;\n}\n\n// kleur wraps strings in ANSI escape codes; padEnd needs the visible width.\nconst ANSI_RE = /\\u001B\\[[0-9;]*m/g;\nfunction visibleLength(s: string): number {\n return s.replace(ANSI_RE, \"\").length;\n}\nfunction padEndVisible(s: string, width: number): string {\n const pad = Math.max(0, width - visibleLength(s));\n return s + \" \".repeat(pad);\n}\n","import kleur from \"kleur\";\n\nexport interface BannerProps {\n /** First content row, e.g. \"164 packages · 2 vulnerable · 2 advisories\". */\n metrics: string;\n /** Second content row, typically a scannedAt ISO timestamp. */\n timestamp: string;\n}\n\nconst BORDER = {\n tl: \"┌\",\n tr: \"┐\",\n bl: \"└\",\n br: \"┘\",\n h: \"─\",\n v: \"│\",\n} as const;\n\nconst TITLE = \"trawly\";\nconst SIDE_PAD = 1; // single space between │ and content\nconst MIN_TITLE_FILLER = 4; // ensure at least \"────\" after `─ trawly `\n\nexport function renderBanner(props: BannerProps): string {\n const contentRows = [props.metrics, props.timestamp];\n const titleSegment = ` ${TITLE} `; // \" trawly \"\n const minTitleWidth = 1 + titleSegment.length + MIN_TITLE_FILLER; // ─ + \" trawly \" + ────\n\n const innerWidth = Math.max(\n ...contentRows.map((r) => r.length + SIDE_PAD * 2),\n minTitleWidth,\n );\n\n const top = renderTop(innerWidth);\n const bottom = renderBottom(innerWidth);\n const metricsLine = renderRow(innerWidth, props.metrics, kleur.bold);\n const timestampLine = renderRow(innerWidth, props.timestamp, kleur.gray);\n\n return [top, metricsLine, timestampLine, bottom].join(\"\\n\");\n}\n\nfunction renderTop(innerWidth: number): string {\n const titleSegment = ` ${kleur.bold().cyan(TITLE)} `;\n const titleVisibleLen = TITLE.length + 2; // bold/cyan don't add visible chars\n const fillerCount = innerWidth - 1 - titleVisibleLen; // -1 for the leading \"─\"\n return (\n kleur.gray(BORDER.tl) +\n kleur.gray(BORDER.h) +\n titleSegment +\n kleur.gray(BORDER.h.repeat(Math.max(MIN_TITLE_FILLER, fillerCount))) +\n kleur.gray(BORDER.tr)\n );\n}\n\nfunction renderBottom(innerWidth: number): string {\n return kleur.gray(`${BORDER.bl}${BORDER.h.repeat(innerWidth)}${BORDER.br}`);\n}\n\nfunction renderRow(\n innerWidth: number,\n content: string,\n colorize: (s: string) => string,\n): string {\n const fill = Math.max(0, innerWidth - SIDE_PAD * 2 - content.length);\n return (\n kleur.gray(BORDER.v) +\n \" \".repeat(SIDE_PAD) +\n colorize(content) +\n \" \".repeat(fill + SIDE_PAD) +\n kleur.gray(BORDER.v)\n );\n}\n"],"mappings":"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","names":["kleur","resolve","resolve","existsSync","readFileSync","join","resolve","at","requested","REQUEST_TIMEOUT_MS","kleur","kleur","kleur","truncate","kleur"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands/add.ts","../src/sources/osv.ts","../src/scanner.ts","../src/extractors/npm-package-lock.ts","../src/extractors/pnpm-lock.ts","../src/extractors/yarn-lock.ts","../src/types.ts","../src/installer/pm-detect.ts","../src/installer/runner.ts","../src/installer/spec-parser.ts","../src/installer/version-resolver.ts","../src/reporters/json.ts","../src/reporters/table.ts","../src/reporters/banner.ts"],"sourcesContent":["import { Command, InvalidArgumentError } from \"commander\";\nimport kleur from \"kleur\";\nimport { reportAdd, runAdd } from \"./commands/add.js\";\nimport {\n buildInstallCommand,\n buildRemoveCommand,\n detectPackageManager,\n type PackageManager,\n} from \"./installer/pm-detect.js\";\nimport { runPackageManager } from \"./installer/runner.js\";\nimport { reportJson } from \"./reporters/json.js\";\nimport { reportTable } from \"./reporters/table.js\";\nimport { meetsThreshold, ScanInputError, scanProject } from \"./scanner.js\";\nimport type { FailOnLevel } from \"./types.js\";\n\nconst FAIL_ON_VALUES: FailOnLevel[] = [\n \"critical\",\n \"high\",\n \"moderate\",\n \"low\",\n \"none\",\n];\nconst FORMAT_VALUES = [\"table\", \"json\"] as const;\ntype Format = (typeof FORMAT_VALUES)[number];\n\nconst PM_VALUES: PackageManager[] = [\"npm\", \"pnpm\", \"yarn\", \"bun\"];\n\nconst EXIT = {\n ok: 0,\n findings: 1,\n operational: 2,\n invalidInput: 3,\n} as const;\n\nfunction parseFailOn(value: string): FailOnLevel {\n if (!FAIL_ON_VALUES.includes(value as FailOnLevel)) {\n throw new InvalidArgumentError(\n `must be one of: ${FAIL_ON_VALUES.join(\", \")}`,\n );\n }\n return value as FailOnLevel;\n}\n\nfunction parseFormat(value: string): Format {\n if (!FORMAT_VALUES.includes(value as Format)) {\n throw new InvalidArgumentError(\n `must be one of: ${FORMAT_VALUES.join(\", \")}`,\n );\n }\n return value as Format;\n}\n\nfunction parsePm(value: string): PackageManager {\n if (!PM_VALUES.includes(value as PackageManager)) {\n throw new InvalidArgumentError(`must be one of: ${PM_VALUES.join(\", \")}`);\n }\n return value as PackageManager;\n}\n\nconst TRAWLY_VERSION = \"0.1.0\";\n\nconst program = new Command();\n\nprogram\n .name(\"trawly\")\n .description(\n \"Dependency sanity scanner. Checks installed npm packages against the OSV advisory database.\",\n )\n .version(TRAWLY_VERSION)\n .enablePositionalOptions()\n .exitOverride((err) => {\n if (err.code === \"commander.helpDisplayed\" || err.code === \"commander.help\") {\n process.exit(EXIT.ok);\n }\n if (err.code === \"commander.version\") process.exit(EXIT.ok);\n process.exit(EXIT.invalidInput);\n });\n\nprogram\n .command(\"scan\", { isDefault: true })\n .description(\n \"Scan a project and gate on findings. Exits non-zero when --fail-on is met. Use `inspect` for a log-only run.\",\n )\n .argument(\"[path]\", \"Project directory to scan\", \".\")\n .option(\n \"--lockfile <path>\",\n \"Explicit path to a lockfile (package-lock.json, pnpm-lock.yaml, or yarn.lock)\",\n )\n .option(\n \"--format <format>\",\n \"Output format: table | json\",\n parseFormat,\n \"table\" as Format,\n )\n .option(\n \"--fail-on <level>\",\n `Exit non-zero when a finding meets this severity (${FAIL_ON_VALUES.join(\"|\")})`,\n parseFailOn,\n \"high\" as FailOnLevel,\n )\n .option(\"--prod\", \"Only scan production dependencies (excludes dev)\")\n .option(\"--include-dev\", \"Include dev dependencies (default)\")\n .option(\"--no-cache\", \"Bypass any local cache\")\n .option(\n \"-v, --details\",\n \"Show one row per advisory (full table). Default groups by package.\",\n )\n .option(\n \"-q, --summary\",\n \"Show only the one-line severity summary. Mutually exclusive with --details.\",\n )\n .action(async (path: string, opts: ScanCliOptions) => {\n await runScanCommand(path, opts, { gate: true });\n });\n\nprogram\n .command(\"inspect\")\n .description(\n \"Scan a project and print findings without gating. Always exits 0 unless an operational error occurs. Use `scan` for CI gating.\",\n )\n .argument(\"[path]\", \"Project directory to scan\", \".\")\n .option(\n \"--lockfile <path>\",\n \"Explicit path to a lockfile (package-lock.json, pnpm-lock.yaml, or yarn.lock)\",\n )\n .option(\n \"--format <format>\",\n \"Output format: table | json\",\n parseFormat,\n \"table\" as Format,\n )\n .option(\"--prod\", \"Only scan production dependencies (excludes dev)\")\n .option(\"--include-dev\", \"Include dev dependencies (default)\")\n .option(\"--no-cache\", \"Bypass any local cache\")\n .option(\n \"-v, --details\",\n \"Show one row per advisory (full table). Default groups by package.\",\n )\n .option(\n \"-q, --summary\",\n \"Show only the one-line severity summary. Mutually exclusive with --details.\",\n )\n .action(async (path: string, opts: InspectCliOptions) => {\n await runScanCommand(\n path,\n { ...opts, failOn: \"none\" as FailOnLevel },\n { gate: false },\n );\n });\n\nprogram\n .command(\"add\")\n .description(\n \"Resolve, scan, and install packages. Vulnerable packages are blocked; clean ones are forwarded to your package manager.\",\n )\n .argument(\"<args...>\", \"Packages to add (e.g. next vitest@1) : PM flags after the first package are passed through\")\n .option(\n \"--fail-on <level>\",\n `Block install when a finding meets this severity (${FAIL_ON_VALUES.join(\"|\")})`,\n parseFailOn,\n \"high\" as FailOnLevel,\n )\n .option(\n \"--pm <name>\",\n `Force a package manager (${PM_VALUES.join(\"|\")}). Auto-detected by default.`,\n parsePm,\n )\n .option(\n \"--allow-vulnerable\",\n \"Install even if vulnerabilities are found (still prints findings).\",\n )\n .passThroughOptions()\n .action(async (args: string[], opts: AddCliOptions) => {\n await executeAdd(args, opts);\n });\n\nprogram\n .command(\"install\")\n .alias(\"i\")\n .description(\n \"Run the project's package manager install. With package args, behaves like `add` (gates on vulnerabilities). With none, forwards directly.\",\n )\n .argument(\"[args...]\", \"Optional packages to add\")\n .option(\n \"--fail-on <level>\",\n `Block install when a finding meets this severity (${FAIL_ON_VALUES.join(\"|\")})`,\n parseFailOn,\n \"high\" as FailOnLevel,\n )\n .option(\n \"--pm <name>\",\n `Force a package manager (${PM_VALUES.join(\"|\")})`,\n parsePm,\n )\n .option(\"--allow-vulnerable\", \"Install even if vulnerabilities are found.\")\n .passThroughOptions()\n .action(async (args: string[], opts: AddCliOptions) => {\n if (args.length === 0) {\n // Bare install: pure passthrough.\n const pm = detectPackageManager({ override: opts.pm });\n const command = buildInstallCommand(pm, []);\n process.stdout.write(\n kleur.gray(`> ${command.bin} ${command.args.join(\" \")}\\n`),\n );\n try {\n const code = await runPackageManager(command);\n process.exit(code);\n } catch (err) {\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n }\n await executeAdd(args, opts);\n });\n\nprogram\n .command(\"remove\")\n .alias(\"uninstall\")\n .description(\n \"Remove packages by delegating to the project's package manager (no scan).\",\n )\n .argument(\"<args...>\", \"Packages to remove\")\n .option(\n \"--pm <name>\",\n `Force a package manager (${PM_VALUES.join(\"|\")})`,\n parsePm,\n )\n .passThroughOptions()\n .action(async (args: string[], opts: { pm?: PackageManager }) => {\n const pm = detectPackageManager({ override: opts.pm });\n const { specs, flags } = splitArgs(args);\n const command = buildRemoveCommand(pm, specs, flags);\n process.stdout.write(\n kleur.gray(`> ${command.bin} ${command.args.join(\" \")}\\n`),\n );\n try {\n const code = await runPackageManager(command);\n process.exit(code);\n } catch (err) {\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n });\n\ninterface ScanCliOptions {\n lockfile?: string;\n format: Format;\n failOn: FailOnLevel;\n prod?: boolean;\n includeDev?: boolean;\n cache?: boolean;\n details?: boolean;\n summary?: boolean;\n}\n\ntype InspectCliOptions = Omit<ScanCliOptions, \"failOn\">;\n\ninterface AddCliOptions {\n failOn: FailOnLevel;\n pm?: PackageManager;\n allowVulnerable?: boolean;\n}\n\nasync function runScanCommand(\n path: string,\n opts: ScanCliOptions,\n { gate }: { gate: boolean },\n): Promise<void> {\n if (opts.prod && opts.includeDev) {\n printErr(\"Cannot combine --prod and --include-dev. Choose one.\");\n process.exit(EXIT.invalidInput);\n }\n if (opts.details && opts.summary) {\n printErr(\"Cannot combine --details and --summary. Choose one.\");\n process.exit(EXIT.invalidInput);\n }\n\n try {\n const result = await scanProject({\n cwd: path,\n lockfile: opts.lockfile,\n includeDev: opts.includeDev,\n prodOnly: opts.prod,\n cache: opts.cache,\n });\n\n if (opts.format === \"json\") {\n process.stdout.write(`${reportJson(result)}\\n`);\n } else {\n const view = opts.summary\n ? \"summary\"\n : opts.details\n ? \"details\"\n : \"grouped\";\n const brand = process.stdout.isTTY === true;\n process.stdout.write(`${reportTable(result, { view, brand })}\\n`);\n }\n\n if (result.errors.length > 0) {\n process.exit(EXIT.operational);\n }\n\n if (!gate) {\n if (opts.format !== \"json\" && result.findings.length > 0) {\n process.stdout.write(\n `${kleur.gray(\n \"ℹ inspect mode: exiting 0 regardless of findings. Run `trawly scan` to gate CI.\",\n )}\\n`,\n );\n }\n process.exit(EXIT.ok);\n }\n\n if (meetsThreshold(result.findings, opts.failOn)) {\n if (opts.format !== \"json\") {\n process.stderr.write(\n `${kleur.red(\n `× Failing because at least one finding meets --fail-on=${opts.failOn}.`,\n )}\\n${kleur.gray(\n \" Run `trawly inspect` to log without exiting non-zero, or `trawly scan --fail-on=none` to disable the gate.\",\n )}\\n`,\n );\n }\n process.exit(EXIT.findings);\n }\n process.exit(EXIT.ok);\n } catch (err) {\n if (err instanceof ScanInputError) {\n printErr(err.message);\n process.exit(EXIT.invalidInput);\n }\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n}\n\nasync function executeAdd(args: string[], opts: AddCliOptions): Promise<void> {\n try {\n const result = await runAdd(args, {\n failOn: opts.failOn,\n pm: opts.pm,\n allowVulnerable: opts.allowVulnerable,\n });\n process.stdout.write(reportAdd(result));\n\n if (result.errored.length > 0) process.exit(EXIT.operational);\n if (result.pmExitCode !== undefined && result.pmExitCode !== 0) {\n process.exit(result.pmExitCode);\n }\n if (result.blocked.length > 0) process.exit(EXIT.findings);\n process.exit(EXIT.ok);\n } catch (err) {\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n}\n\nfunction splitArgs(args: string[]): { specs: string[]; flags: string[] } {\n const specs: string[] = [];\n const flags: string[] = [];\n for (const a of args) {\n if (a.startsWith(\"-\")) flags.push(a);\n else specs.push(a);\n }\n return { specs, flags };\n}\n\nfunction printErr(msg: string): void {\n process.stderr.write(`${kleur.red(msg)}\\n`);\n}\n\nawait program.parseAsync(process.argv);\n","import kleur from \"kleur\";\nimport { queryOsv } from \"../sources/osv.js\";\nimport { compareFindings, summarize } from \"../scanner.js\";\nimport { SEVERITY_RANK } from \"../types.js\";\nimport type { Finding, PackageInstance, Severity } from \"../types.js\";\nimport {\n buildAddCommand,\n detectPackageManager,\n type PackageManager,\n} from \"../installer/pm-detect.js\";\nimport { runPackageManager } from \"../installer/runner.js\";\nimport {\n parseSpec,\n partitionArgs,\n type ParsedSpec,\n type UnsupportedReason,\n} from \"../installer/spec-parser.js\";\nimport {\n resolveVersion,\n VersionResolveError,\n type ResolvedVersion,\n} from \"../installer/version-resolver.js\";\n\nexport interface AddOptions {\n cwd?: string;\n pm?: PackageManager;\n failOn: Severity | \"none\";\n allowVulnerable?: boolean;\n fetchImpl?: typeof fetch;\n /** Test seam: replace the real spawn with a stub. */\n runner?: typeof runPackageManager;\n}\n\nexport interface AddResult {\n /** Specs we sent to the package manager. */\n installed: ResolvedSpec[];\n /** Specs we refused to install. */\n blocked: BlockedSpec[];\n /** Specs we couldn't analyze (git, file, url, alias). */\n skipped: SkippedSpec[];\n /** Specs that failed registry resolution. */\n errored: ErroredSpec[];\n /** All findings collected, sorted. */\n findings: Finding[];\n /** Exit code from the PM, or undefined if we never ran it. */\n pmExitCode?: number;\n}\n\ninterface ResolvedSpec {\n spec: ParsedSpec;\n resolved: ResolvedVersion;\n findings: Finding[];\n}\n\ninterface BlockedSpec extends ResolvedSpec {\n reason: \"vulnerable\";\n}\n\ninterface SkippedSpec {\n spec: ParsedSpec;\n reason: UnsupportedReason;\n}\n\ninterface ErroredSpec {\n spec: ParsedSpec;\n message: string;\n}\n\nexport async function runAdd(\n args: string[],\n options: AddOptions,\n): Promise<AddResult> {\n const { specs, flags } = partitionArgs(args);\n\n const skipped: SkippedSpec[] = [];\n const resolvable: ParsedSpec[] = [];\n for (const spec of specs) {\n if (spec.unsupported) {\n skipped.push({ spec, reason: spec.unsupported });\n } else {\n resolvable.push(spec);\n }\n }\n\n const resolved: ResolvedSpec[] = [];\n const errored: ErroredSpec[] = [];\n await Promise.all(\n resolvable.map(async (spec) => {\n try {\n const r = await resolveVersion(spec.name, spec.requested, {\n fetchImpl: options.fetchImpl,\n });\n resolved.push({ spec, resolved: r, findings: [] });\n } catch (err) {\n const message =\n err instanceof VersionResolveError\n ? err.message\n : `Registry error: ${(err as Error).message}`;\n errored.push({ spec, message });\n }\n }),\n );\n\n let findings: Finding[] = [];\n if (resolved.length > 0) {\n const instances: PackageInstance[] = resolved.map((r) => ({\n name: r.spec.name,\n version: r.resolved.version,\n ecosystem: \"npm\",\n path: r.spec.raw,\n direct: true,\n dev: false,\n optional: false,\n }));\n try {\n findings = await queryOsv(instances, { fetchImpl: options.fetchImpl });\n } catch (err) {\n // If OSV is unreachable we cannot make a safe call; treat as a hard error\n // for every resolvable spec rather than silently letting installs through.\n const message = `OSV query failed: ${(err as Error).message}`;\n for (const r of resolved) errored.push({ spec: r.spec, message });\n resolved.length = 0;\n }\n }\n\n for (const f of findings) {\n const owner = resolved.find(\n (r) => r.spec.name === f.packageName && r.resolved.version === f.installedVersion,\n );\n if (owner) owner.findings.push(f);\n }\n\n const blocked: BlockedSpec[] = [];\n const installed: ResolvedSpec[] = [];\n for (const r of resolved) {\n if (shouldBlock(r.findings, options)) {\n blocked.push({ ...r, reason: \"vulnerable\" });\n } else {\n installed.push(r);\n }\n }\n\n findings.sort(compareFindings);\n\n let pmExitCode: number | undefined;\n if (installed.length > 0) {\n const pm = detectPackageManager({ override: options.pm, cwd: options.cwd });\n const cmd = buildAddCommand(\n pm,\n installed.map((r) => r.spec.raw),\n flags,\n );\n process.stdout.write(\n kleur.gray(`> ${cmd.bin} ${cmd.args.join(\" \")}\\n`),\n );\n const runner = options.runner ?? runPackageManager;\n pmExitCode = await runner(cmd, { cwd: options.cwd });\n }\n\n return { installed, blocked, skipped, errored, findings, pmExitCode };\n}\n\nexport function reportAdd(result: AddResult): string {\n const lines: string[] = [];\n\n if (result.skipped.length > 0) {\n for (const s of result.skipped) {\n lines.push(\n kleur.yellow(\n `~ Skipped ${s.spec.raw}: ${describeUnsupported(s.reason)} (cannot scan; not forwarded to install)`,\n ),\n );\n }\n }\n\n if (result.errored.length > 0) {\n for (const e of result.errored) {\n lines.push(kleur.red(`! ${e.spec.raw}: ${e.message}`));\n }\n }\n\n if (result.blocked.length > 0) {\n for (const b of result.blocked) {\n const sev = summarize(b.findings);\n const counts = describeSeverityCounts(sev);\n lines.push(\n kleur.red(\n `✗ Blocked ${b.spec.name}@${b.resolved.version}: ${counts}`,\n ),\n );\n if (b.resolved.source === \"fallback-latest\") {\n lines.push(\n kleur.gray(\n ` (scanned latest because we don't resolve semver ranges yet; you asked for \"${b.resolved.requested}\")`,\n ),\n );\n }\n for (const f of b.findings) {\n lines.push(\n ` - [${colorSeverity(f.severity)}] ${f.id} : ${f.summary}`,\n );\n if (f.fixedVersions.length > 0) {\n lines.push(kleur.gray(` fixed in: ${f.fixedVersions.join(\", \")}`));\n }\n if (f.url) lines.push(kleur.gray(` ${f.url}`));\n }\n }\n }\n\n if (result.installed.length > 0) {\n const names = result.installed\n .map((r) => `${r.spec.name}@${r.resolved.version}`)\n .join(\", \");\n lines.push(kleur.green(`✓ Installing: ${names}`));\n } else if (result.blocked.length > 0) {\n lines.push(\n kleur.red(\"Nothing installed : all requested packages were blocked.\"),\n );\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction shouldBlock(findings: Finding[], options: AddOptions): boolean {\n if (options.allowVulnerable) return false;\n if (options.failOn === \"none\") return false;\n const threshold = SEVERITY_RANK[options.failOn];\n return findings.some((f) => SEVERITY_RANK[f.severity] >= threshold);\n}\n\nfunction describeUnsupported(reason: UnsupportedReason): string {\n switch (reason) {\n case \"git\":\n return \"git specs cannot be scanned against OSV\";\n case \"url\":\n return \"URL specs cannot be scanned against OSV\";\n case \"file\":\n return \"local file specs cannot be scanned against OSV\";\n case \"alias\":\n return \"npm aliases are not supported in v1\";\n case \"workspace\":\n return \"workspace protocol specs are not scanned\";\n case \"invalid\":\n return \"could not parse spec\";\n }\n}\n\nfunction describeSeverityCounts(summary: Record<Severity, number>): string {\n const parts: string[] = [];\n for (const sev of [\"critical\", \"high\", \"moderate\", \"low\", \"unknown\"] as Severity[]) {\n if (summary[sev] > 0) parts.push(`${summary[sev]} ${sev}`);\n }\n return parts.length === 0 ? \"no advisories\" : `${parts.join(\", \")} advisor${total(summary) === 1 ? \"y\" : \"ies\"}`;\n}\n\nfunction total(summary: Record<Severity, number>): number {\n return Object.values(summary).reduce((a, b) => a + b, 0);\n}\n\nfunction colorSeverity(sev: Severity): string {\n switch (sev) {\n case \"critical\":\n return kleur.bold().red(sev);\n case \"high\":\n return kleur.red(sev);\n case \"moderate\":\n return kleur.yellow(sev);\n case \"low\":\n return kleur.cyan(sev);\n case \"unknown\":\n return kleur.gray(sev);\n }\n}\n\n// Re-exports so tests can poke at the parsed spec type.\nexport { parseSpec };\n","import type { Finding, PackageInstance, Severity } from \"../types.js\";\n\nconst OSV_QUERYBATCH_URL = \"https://api.osv.dev/v1/querybatch\";\nconst OSV_VULN_URL = \"https://api.osv.dev/v1/vulns\";\nconst QUERY_CHUNK_SIZE = 500;\nconst REQUEST_TIMEOUT_MS = 15_000;\nconst MAX_RETRIES = 2;\n\ninterface OsvQueryBatchResponse {\n results: Array<{ vulns?: Array<{ id: string; modified?: string }> }>;\n}\n\ninterface OsvSeverity {\n type: string;\n score: string;\n}\n\ninterface OsvAffectedRange {\n type: string;\n events: Array<{ introduced?: string; fixed?: string; last_affected?: string }>;\n}\n\ninterface OsvAffectedPackage {\n package?: { ecosystem?: string; name?: string };\n ranges?: OsvAffectedRange[];\n versions?: string[];\n}\n\ninterface OsvVulnDetail {\n id: string;\n summary?: string;\n details?: string;\n references?: Array<{ type?: string; url?: string }>;\n severity?: OsvSeverity[];\n database_specific?: { severity?: string };\n affected?: OsvAffectedPackage[];\n}\n\nexport interface OsvQueryDeps {\n fetchImpl?: typeof fetch;\n}\n\ninterface UniquePackage {\n name: string;\n version: string;\n}\n\n/**\n * Build the deduplicated list of unique name@version pairs to query OSV with.\n */\nexport function dedupeForQuery(\n packages: PackageInstance[],\n): UniquePackage[] {\n const seen = new Set<string>();\n const out: UniquePackage[] = [];\n for (const pkg of packages) {\n const key = `${pkg.name}@${pkg.version}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push({ name: pkg.name, version: pkg.version });\n }\n return out;\n}\n\n/**\n * Query OSV for the given installed packages and return one Finding per\n * (advisory, affected package instance) pair.\n */\nexport async function queryOsv(\n packages: PackageInstance[],\n deps: OsvQueryDeps = {},\n): Promise<Finding[]> {\n const fetchImpl = deps.fetchImpl ?? fetch;\n const unique = dedupeForQuery(packages);\n if (unique.length === 0) return [];\n\n const idsByPackage = new Map<string, Set<string>>();\n for (const chunk of chunked(unique, QUERY_CHUNK_SIZE)) {\n const body = {\n queries: chunk.map((q) => ({\n package: { ecosystem: \"npm\", name: q.name },\n version: q.version,\n })),\n };\n const res = await postJson<OsvQueryBatchResponse>(\n fetchImpl,\n OSV_QUERYBATCH_URL,\n body,\n );\n res.results.forEach((result, i) => {\n const q = chunk[i];\n if (!q) return;\n const key = `${q.name}@${q.version}`;\n if (!result.vulns || result.vulns.length === 0) return;\n const ids = idsByPackage.get(key) ?? new Set<string>();\n for (const v of result.vulns) ids.add(v.id);\n idsByPackage.set(key, ids);\n });\n }\n\n const allIds = new Set<string>();\n for (const ids of idsByPackage.values()) {\n for (const id of ids) allIds.add(id);\n }\n\n const detailsById = new Map<string, OsvVulnDetail>();\n for (const id of allIds) {\n try {\n const detail = await getJson<OsvVulnDetail>(\n fetchImpl,\n `${OSV_VULN_URL}/${encodeURIComponent(id)}`,\n );\n detailsById.set(id, detail);\n } catch {\n // Skip missing/broken records; we still have the id reported below.\n }\n }\n\n const findings: Finding[] = [];\n for (const pkg of packages) {\n const key = `${pkg.name}@${pkg.version}`;\n const ids = idsByPackage.get(key);\n if (!ids) continue;\n for (const id of ids) {\n const detail = detailsById.get(id);\n findings.push(buildFinding(pkg, id, detail));\n }\n }\n return findings;\n}\n\nfunction buildFinding(\n pkg: PackageInstance,\n id: string,\n detail: OsvVulnDetail | undefined,\n): Finding {\n const severity = detail ? parseSeverity(detail) : \"unknown\";\n const summary = detail?.summary ?? detail?.details ?? id;\n return {\n id,\n source: \"osv\",\n type: \"vulnerability\",\n severity,\n packageName: pkg.name,\n installedVersion: pkg.version,\n summary: truncate(summary, 240),\n url: pickAdvisoryUrl(detail) ?? `https://osv.dev/vulnerability/${id}`,\n fixedVersions: detail ? collectFixedVersions(detail, pkg.name) : [],\n affectedPaths: [pkg.path],\n };\n}\n\nexport function parseSeverity(detail: OsvVulnDetail): Severity {\n // GHSA records expose a normalized severity in database_specific.severity.\n const dbSpecific = detail.database_specific?.severity?.toLowerCase();\n if (\n dbSpecific === \"critical\" ||\n dbSpecific === \"high\" ||\n dbSpecific === \"moderate\" ||\n dbSpecific === \"low\"\n ) {\n return dbSpecific;\n }\n if (dbSpecific === \"medium\") return \"moderate\";\n\n const cvss = detail.severity?.find((s) => s.type?.startsWith(\"CVSS_\"));\n if (cvss) {\n const score = parseCvssScore(cvss.score);\n if (score === undefined) return \"unknown\";\n if (score >= 9.0) return \"critical\";\n if (score >= 7.0) return \"high\";\n if (score >= 4.0) return \"moderate\";\n if (score > 0) return \"low\";\n }\n return \"unknown\";\n}\n\nfunction parseCvssScore(vector: string): number | undefined {\n const direct = Number.parseFloat(vector);\n if (!Number.isNaN(direct) && vector.trim() !== \"\") return direct;\n // Some entries store the full CVSS vector string; we don't compute it here.\n return undefined;\n}\n\nfunction pickAdvisoryUrl(detail: OsvVulnDetail | undefined): string | undefined {\n if (!detail?.references) return undefined;\n const advisory = detail.references.find((r) => r.type === \"ADVISORY\");\n return advisory?.url ?? detail.references[0]?.url;\n}\n\nexport function collectFixedVersions(\n detail: OsvVulnDetail,\n packageName: string,\n): string[] {\n const out = new Set<string>();\n for (const aff of detail.affected ?? []) {\n if (aff.package?.name && aff.package.name !== packageName) continue;\n for (const range of aff.ranges ?? []) {\n for (const event of range.events ?? []) {\n if (event.fixed) out.add(event.fixed);\n }\n }\n }\n return [...out];\n}\n\nfunction* chunked<T>(items: T[], size: number): Generator<T[]> {\n for (let i = 0; i < items.length; i += size) {\n yield items.slice(i, i + size);\n }\n}\n\nasync function postJson<T>(\n fetchImpl: typeof fetch,\n url: string,\n body: unknown,\n): Promise<T> {\n return withRetry(async () => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n const res = await fetchImpl(url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n throw new HttpError(`OSV ${res.status}: ${res.statusText}`, res.status);\n }\n return (await res.json()) as T;\n } finally {\n clearTimeout(timer);\n }\n });\n}\n\nasync function getJson<T>(fetchImpl: typeof fetch, url: string): Promise<T> {\n return withRetry(async () => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n const res = await fetchImpl(url, { signal: controller.signal });\n if (!res.ok) {\n throw new HttpError(`OSV ${res.status}: ${res.statusText}`, res.status);\n }\n return (await res.json()) as T;\n } finally {\n clearTimeout(timer);\n }\n });\n}\n\nclass HttpError extends Error {\n constructor(message: string, public readonly status: number) {\n super(message);\n }\n}\n\nasync function withRetry<T>(fn: () => Promise<T>): Promise<T> {\n let lastErr: unknown;\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastErr = err;\n if (!isRetryable(err) || attempt === MAX_RETRIES) break;\n await new Promise((r) => setTimeout(r, 250 * 2 ** attempt));\n }\n }\n throw lastErr;\n}\n\nfunction isRetryable(err: unknown): boolean {\n if (err instanceof HttpError) return err.status >= 500;\n // AbortError (timeout) and network errors are retryable.\n return true;\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return `${s.slice(0, max - 1)}…`;\n}\n","import { existsSync, statSync } from \"node:fs\";\nimport { basename, resolve, join } from \"node:path\";\nimport { parseNpmPackageLock } from \"./extractors/npm-package-lock.js\";\nimport { parsePnpmLock } from \"./extractors/pnpm-lock.js\";\nimport { parseYarnLock } from \"./extractors/yarn-lock.js\";\nimport { queryOsv } from \"./sources/osv.js\";\nimport { SEVERITY_RANK } from \"./types.js\";\nimport type {\n Finding,\n PackageInstance,\n ScanError,\n ScanLockfileOptions,\n ScanProjectOptions,\n ScanResult,\n Severity,\n} from \"./types.js\";\n\nexport async function scanProject(\n options: ScanProjectOptions = {},\n): Promise<ScanResult> {\n const cwd = resolve(options.cwd ?? process.cwd());\n const lockfilePath = options.lockfile\n ? resolve(cwd, options.lockfile)\n : detectLockfile(cwd);\n\n if (!lockfilePath) {\n throw new ScanInputError(\n `No supported lockfile found in ${cwd}. Pass --lockfile or run in a directory with package-lock.json, pnpm-lock.yaml, or yarn.lock.`,\n );\n }\n\n return scanLockfile({\n lockfilePath,\n includeDev: options.includeDev,\n prodOnly: options.prodOnly,\n fetchImpl: options.fetchImpl,\n });\n}\n\nexport async function scanLockfile(\n options: ScanLockfileOptions,\n): Promise<ScanResult> {\n const { lockfilePath } = options;\n if (!existsSync(lockfilePath)) {\n throw new ScanInputError(`Lockfile does not exist: ${lockfilePath}`);\n }\n const stat = statSync(lockfilePath);\n if (!stat.isFile()) {\n throw new ScanInputError(`Lockfile path is not a file: ${lockfilePath}`);\n }\n\n const allInstances = parseLockfile(lockfilePath);\n const instances = filterInstances(allInstances, options);\n const errors: ScanError[] = [];\n\n let findings: Finding[] = [];\n try {\n findings = await queryOsv(instances, { fetchImpl: options.fetchImpl });\n } catch (err) {\n errors.push({\n message: \"Failed to query OSV advisory database\",\n cause: (err as Error).message,\n });\n }\n\n findings.sort(compareFindings);\n\n return {\n scannedAt: new Date().toISOString(),\n packagesScanned: instances.length,\n findings,\n summary: summarize(findings),\n errors,\n };\n}\n\nexport class ScanInputError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ScanInputError\";\n }\n}\n\nconst LOCKFILE_CANDIDATES = [\n \"pnpm-lock.yaml\",\n \"yarn.lock\",\n \"package-lock.json\",\n \"npm-shrinkwrap.json\",\n] as const;\n\nfunction detectLockfile(cwd: string): string | undefined {\n for (const file of LOCKFILE_CANDIDATES) {\n const candidate = join(cwd, file);\n if (existsSync(candidate)) return candidate;\n }\n return undefined;\n}\n\nfunction parseLockfile(lockfilePath: string): PackageInstance[] {\n const name = basename(lockfilePath);\n if (name === \"pnpm-lock.yaml\") return parsePnpmLock(lockfilePath);\n if (name === \"yarn.lock\") return parseYarnLock(lockfilePath);\n if (name === \"package-lock.json\" || name === \"npm-shrinkwrap.json\") {\n return parseNpmPackageLock(lockfilePath);\n }\n throw new ScanInputError(\n `Unsupported lockfile name: ${name}. Supported: package-lock.json, npm-shrinkwrap.json, pnpm-lock.yaml, yarn.lock.`,\n );\n}\n\nfunction filterInstances(\n instances: PackageInstance[],\n options: { includeDev?: boolean; prodOnly?: boolean },\n): PackageInstance[] {\n const includeDev = options.prodOnly ? false : options.includeDev !== false;\n if (includeDev) return instances;\n return instances.filter((p) => !p.dev);\n}\n\nexport function compareFindings(a: Finding, b: Finding): number {\n const sev = SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity];\n if (sev !== 0) return sev;\n if (a.packageName !== b.packageName) {\n return a.packageName.localeCompare(b.packageName);\n }\n if (a.installedVersion !== b.installedVersion) {\n return a.installedVersion.localeCompare(b.installedVersion);\n }\n return a.id.localeCompare(b.id);\n}\n\nexport function summarize(findings: Finding[]): Record<Severity, number> {\n const summary: Record<Severity, number> = {\n critical: 0,\n high: 0,\n moderate: 0,\n low: 0,\n unknown: 0,\n };\n for (const f of findings) summary[f.severity]++;\n return summary;\n}\n\n/**\n * Returns true when any finding meets or exceeds the given severity threshold.\n * \"none\" means never fail.\n */\nexport function meetsThreshold(\n findings: Finding[],\n threshold: Severity | \"none\",\n): boolean {\n if (threshold === \"none\") return false;\n const min = SEVERITY_RANK[threshold];\n return findings.some((f) => SEVERITY_RANK[f.severity] >= min);\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { PackageInstance } from \"../types.js\";\n\ninterface NpmLockEntry {\n version?: string;\n resolved?: string;\n integrity?: string;\n dev?: boolean;\n devOptional?: boolean;\n optional?: boolean;\n peer?: boolean;\n link?: boolean;\n // Present on the root (\"\") entry only.\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\ninterface NpmLockfile {\n name?: string;\n lockfileVersion?: number;\n packages?: Record<string, NpmLockEntry>;\n}\n\n/**\n * Parse an npm `package-lock.json` (v2 or v3) and return one\n * PackageInstance per node in the `packages` map.\n *\n * The empty-string key represents the root project and is skipped.\n */\nexport function parseNpmPackageLock(filePath: string): PackageInstance[] {\n const absolute = resolve(filePath);\n const raw = readFileSync(absolute, \"utf8\");\n let parsed: NpmLockfile;\n try {\n parsed = JSON.parse(raw) as NpmLockfile;\n } catch (err) {\n throw new Error(\n `Failed to parse ${absolute}: ${(err as Error).message}`,\n );\n }\n\n if (parsed.lockfileVersion !== 2 && parsed.lockfileVersion !== 3) {\n throw new Error(\n `Unsupported npm lockfileVersion ${String(\n parsed.lockfileVersion,\n )} in ${absolute}. Only v2 and v3 are supported.`,\n );\n }\n\n const packages = parsed.packages;\n if (!packages || typeof packages !== \"object\") {\n throw new Error(\n `Lockfile ${absolute} has no \"packages\" map; cannot extract installed versions.`,\n );\n }\n\n const directDeps = collectDirectDependencyNames(packages[\"\"] ?? {});\n const instances: PackageInstance[] = [];\n\n for (const [path, entry] of Object.entries(packages)) {\n if (path === \"\") continue;\n if (entry.link) continue; // workspace symlink, not a real install\n const name = packagePathToName(path);\n if (!name) continue;\n if (!entry.version) continue;\n\n instances.push({\n name,\n version: entry.version,\n ecosystem: \"npm\",\n path,\n direct: directDeps.has(name) && isTopLevelInstance(path),\n dev: Boolean(entry.dev || entry.devOptional),\n optional: Boolean(entry.optional || entry.devOptional),\n resolved: entry.resolved,\n integrity: entry.integrity,\n });\n }\n\n return instances;\n}\n\nfunction collectDirectDependencyNames(rootEntry: NpmLockEntry): Set<string> {\n const names = new Set<string>();\n for (const key of [\n \"dependencies\",\n \"devDependencies\",\n \"optionalDependencies\",\n \"peerDependencies\",\n ] as const) {\n const block = rootEntry[key];\n if (!block) continue;\n for (const name of Object.keys(block)) names.add(name);\n }\n return names;\n}\n\n/**\n * \"node_modules/foo\" -> \"foo\"\n * \"node_modules/@scope/bar\" -> \"@scope/bar\"\n * \"node_modules/foo/node_modules/bar\" -> \"bar\"\n */\nexport function packagePathToName(path: string): string | null {\n const marker = \"node_modules/\";\n const idx = path.lastIndexOf(marker);\n if (idx === -1) return null;\n const tail = path.slice(idx + marker.length);\n if (!tail) return null;\n if (tail.startsWith(\"@\")) {\n const firstSlash = tail.indexOf(\"/\");\n if (firstSlash === -1) return null;\n const secondSlash = tail.indexOf(\"/\", firstSlash + 1);\n return secondSlash === -1 ? tail : tail.slice(0, secondSlash);\n }\n const next = tail.indexOf(\"/\");\n return next === -1 ? tail : tail.slice(0, next);\n}\n\n/** A direct-install path has exactly one `node_modules/` segment. */\nfunction isTopLevelInstance(path: string): boolean {\n const first = path.indexOf(\"node_modules/\");\n if (first === -1) return false;\n return path.indexOf(\"node_modules/\", first + 1) === -1;\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport yaml from \"js-yaml\";\nimport type { PackageInstance } from \"../types.js\";\n\ninterface PnpmDepRef {\n specifier?: string;\n version?: string;\n}\n\ntype PnpmImporterDeps = Record<string, string | PnpmDepRef>;\n\ninterface PnpmImporter {\n dependencies?: PnpmImporterDeps;\n devDependencies?: PnpmImporterDeps;\n optionalDependencies?: PnpmImporterDeps;\n}\n\ninterface PnpmPackageEntry {\n resolution?: { integrity?: string; tarball?: string };\n name?: string;\n version?: string;\n dev?: boolean;\n optional?: boolean;\n}\n\ninterface PnpmLockfile {\n lockfileVersion?: number | string;\n importers?: Record<string, PnpmImporter>;\n packages?: Record<string, PnpmPackageEntry>;\n // v6 root-level deps when no importers section\n dependencies?: PnpmImporterDeps;\n devDependencies?: PnpmImporterDeps;\n optionalDependencies?: PnpmImporterDeps;\n}\n\nconst SUPPORTED_MAJOR_VERSIONS = new Set([6, 9]);\n\nexport function parsePnpmLock(filePath: string): PackageInstance[] {\n const absolute = resolve(filePath);\n const raw = readFileSync(absolute, \"utf8\");\n let parsed: PnpmLockfile;\n try {\n parsed = (yaml.load(raw) ?? {}) as PnpmLockfile;\n } catch (err) {\n throw new Error(\n `Failed to parse ${absolute}: ${(err as Error).message}`,\n );\n }\n\n const versionRaw = parsed.lockfileVersion;\n const major = parseLockfileMajor(versionRaw);\n if (major === null || !SUPPORTED_MAJOR_VERSIONS.has(major)) {\n throw new Error(\n `Unsupported pnpm lockfileVersion ${String(versionRaw)} in ${absolute}. Supported: 6.x, 9.x.`,\n );\n }\n\n const packages = parsed.packages;\n if (!packages || typeof packages !== \"object\") {\n throw new Error(\n `Lockfile ${absolute} has no \"packages\" map; cannot extract installed versions.`,\n );\n }\n\n const importers = parsed.importers ?? {\n \".\": {\n dependencies: parsed.dependencies,\n devDependencies: parsed.devDependencies,\n optionalDependencies: parsed.optionalDependencies,\n },\n };\n\n const direct = collectDirectFromImporters(importers);\n const instances: PackageInstance[] = [];\n\n for (const [key, entry] of Object.entries(packages)) {\n const parsed = parsePnpmPackageKey(key);\n if (!parsed) continue;\n const name = entry.name ?? parsed.name;\n const version = entry.version ?? parsed.version;\n if (!name || !version) continue;\n\n const isDirect = direct.prod.has(name) || direct.dev.has(name) || direct.optional.has(name);\n const onlyDev = direct.dev.has(name) && !direct.prod.has(name);\n const onlyOptional =\n direct.optional.has(name) && !direct.prod.has(name) && !direct.dev.has(name);\n\n instances.push({\n name,\n version,\n ecosystem: \"npm\",\n path: key,\n direct: isDirect,\n dev: Boolean(entry.dev) || onlyDev,\n optional: Boolean(entry.optional) || onlyOptional,\n resolved: entry.resolution?.tarball,\n integrity: entry.resolution?.integrity,\n });\n }\n\n return instances;\n}\n\nfunction parseLockfileMajor(value: unknown): number | null {\n if (typeof value === \"number\") return Math.trunc(value);\n if (typeof value === \"string\") {\n const num = parseInt(value, 10);\n return Number.isNaN(num) ? null : num;\n }\n return null;\n}\n\ninterface DirectSets {\n prod: Set<string>;\n dev: Set<string>;\n optional: Set<string>;\n}\n\nfunction collectDirectFromImporters(\n importers: Record<string, PnpmImporter>,\n): DirectSets {\n const prod = new Set<string>();\n const dev = new Set<string>();\n const optional = new Set<string>();\n for (const importer of Object.values(importers)) {\n if (!importer) continue;\n addDepNames(importer.dependencies, prod);\n addDepNames(importer.devDependencies, dev);\n addDepNames(importer.optionalDependencies, optional);\n }\n return { prod, dev, optional };\n}\n\nfunction addDepNames(block: PnpmImporterDeps | undefined, into: Set<string>): void {\n if (!block) return;\n for (const name of Object.keys(block)) into.add(name);\n}\n\n/**\n * pnpm v9: \"lodash@4.17.21\", \"@scope/foo@1.2.3\", \"vitest@2.0.0(peer)\"\n * pnpm v6: \"/lodash@4.17.21\", \"/@scope/foo@1.2.3\", \"/vitest@2.0.0(peer)\"\n */\nexport function parsePnpmPackageKey(\n key: string,\n): { name: string; version: string } | null {\n let working = key.startsWith(\"/\") ? key.slice(1) : key;\n // Strip peer-deps suffix (everything from the first paren onward).\n const parenIdx = working.indexOf(\"(\");\n if (parenIdx !== -1) working = working.slice(0, parenIdx);\n\n // Find the @ separating name from version. For scoped names (@scope/foo@x.y.z)\n // we must skip the leading @.\n const startSearch = working.startsWith(\"@\") ? 1 : 0;\n const atIdx = working.indexOf(\"@\", startSearch);\n if (atIdx <= 0) return null;\n const name = working.slice(0, atIdx);\n const version = working.slice(atIdx + 1);\n if (!name || !version) return null;\n return { name, version };\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport yaml from \"js-yaml\";\nimport type { PackageInstance } from \"../types.js\";\n\ninterface YarnEntry {\n specs: string[];\n fields: Record<string, string>;\n}\n\ninterface BerryEntry {\n version?: string;\n resolution?: string;\n checksum?: string;\n // language and linker keys are ignored\n}\n\n/**\n * Parse a yarn lockfile (classic v1 or berry v2+) and return one\n * PackageInstance per resolved entry.\n *\n * Direct/dev flags are inferred by reading the sibling package.json,\n * since yarn lockfiles don't carry that information themselves.\n */\nexport function parseYarnLock(filePath: string): PackageInstance[] {\n const absolute = resolve(filePath);\n const content = readFileSync(absolute, \"utf8\");\n const projectDir = dirname(absolute);\n const directs = readDirectDepsFromPackageJson(projectDir);\n const isBerry = /^__metadata:/m.test(content);\n return isBerry\n ? parseBerry(absolute, content, directs)\n : parseClassic(absolute, content, directs);\n}\n\ninterface DirectSets {\n prod: Set<string>;\n dev: Set<string>;\n optional: Set<string>;\n any: Set<string>;\n}\n\nfunction readDirectDepsFromPackageJson(projectDir: string): DirectSets {\n const result: DirectSets = {\n prod: new Set(),\n dev: new Set(),\n optional: new Set(),\n any: new Set(),\n };\n const pkgPath = join(projectDir, \"package.json\");\n if (!existsSync(pkgPath)) return result;\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n };\n for (const name of Object.keys(pkg.dependencies ?? {})) result.prod.add(name);\n for (const name of Object.keys(pkg.devDependencies ?? {})) result.dev.add(name);\n for (const name of Object.keys(pkg.optionalDependencies ?? {}))\n result.optional.add(name);\n for (const set of [result.prod, result.dev, result.optional]) {\n for (const n of set) result.any.add(n);\n }\n for (const name of Object.keys(pkg.peerDependencies ?? {})) result.any.add(name);\n } catch {\n // malformed package.json: leave sets empty\n }\n return result;\n}\n\n// ---------- yarn classic v1 ----------\n\nfunction parseClassic(\n absolute: string,\n content: string,\n directs: DirectSets,\n): PackageInstance[] {\n const entries = parseClassicEntries(content);\n const instances: PackageInstance[] = [];\n for (const entry of entries) {\n const version = entry.fields.version;\n if (!version) continue;\n const names = uniq(entry.specs.map((s) => parseYarnSpec(s).name).filter(Boolean));\n const name = names[0];\n if (!name) continue;\n const isDirect = names.some((n) => directs.any.has(n));\n const inProd = names.some((n) => directs.prod.has(n));\n const inDev = names.some((n) => directs.dev.has(n));\n const inOpt = names.some((n) => directs.optional.has(n));\n instances.push({\n name,\n version,\n ecosystem: \"npm\",\n path: `${name}@${version}`,\n direct: isDirect,\n dev: inDev && !inProd,\n optional: inOpt && !inProd && !inDev,\n resolved: entry.fields.resolved,\n integrity: entry.fields.integrity,\n });\n }\n void absolute;\n return instances;\n}\n\nexport function parseClassicEntries(content: string): YarnEntry[] {\n const lines = content.split(/\\r?\\n/);\n const entries: YarnEntry[] = [];\n let current: YarnEntry | null = null;\n for (const rawLine of lines) {\n if (rawLine === \"\" || rawLine.trimStart().startsWith(\"#\")) continue;\n if (!/^\\s/.test(rawLine)) {\n // Header line ending with \":\"\n if (current) entries.push(current);\n const header = rawLine.replace(/:\\s*$/, \"\");\n current = { specs: splitClassicSpecs(header), fields: {} };\n continue;\n }\n if (!current) continue;\n // Top-level field for this entry has indent of exactly 2 spaces.\n const indent = rawLine.match(/^ +/)?.[0].length ?? 0;\n if (indent !== 2) continue;\n const trimmed = rawLine.trim();\n const m =\n trimmed.match(/^([^\\s\"]+)\\s+\"((?:[^\"\\\\]|\\\\.)*)\"$/) ??\n trimmed.match(/^([^\\s\"]+)\\s+(\\S+)$/);\n if (m && m[1] !== undefined && m[2] !== undefined) {\n current.fields[m[1]] = m[2];\n }\n }\n if (current) entries.push(current);\n return entries;\n}\n\nfunction splitClassicSpecs(header: string): string[] {\n const out: string[] = [];\n let cur = \"\";\n let inQuote = false;\n for (const ch of header) {\n if (ch === '\"') {\n inQuote = !inQuote;\n continue;\n }\n if (ch === \",\" && !inQuote) {\n const spec = cur.trim();\n if (spec) out.push(spec);\n cur = \"\";\n continue;\n }\n cur += ch;\n }\n const last = cur.trim();\n if (last) out.push(last);\n return out;\n}\n\n// ---------- yarn berry (v2+) ----------\n\nfunction parseBerry(\n absolute: string,\n content: string,\n directs: DirectSets,\n): PackageInstance[] {\n let parsed: Record<string, BerryEntry | unknown>;\n try {\n parsed = (yaml.load(content) ?? {}) as Record<string, BerryEntry | unknown>;\n } catch (err) {\n throw new Error(\n `Failed to parse ${absolute}: ${(err as Error).message}`,\n );\n }\n const instances: PackageInstance[] = [];\n for (const [key, value] of Object.entries(parsed)) {\n if (key === \"__metadata\") continue;\n if (!value || typeof value !== \"object\") continue;\n const entry = value as BerryEntry;\n if (!entry.version) continue;\n const specs = splitClassicSpecs(key);\n const names = uniq(specs.map((s) => parseYarnSpec(s).name).filter(Boolean));\n const name = names[0];\n if (!name) continue;\n const isDirect = names.some((n) => directs.any.has(n));\n const inProd = names.some((n) => directs.prod.has(n));\n const inDev = names.some((n) => directs.dev.has(n));\n const inOpt = names.some((n) => directs.optional.has(n));\n instances.push({\n name,\n version: entry.version,\n ecosystem: \"npm\",\n path: `${name}@${entry.version}`,\n direct: isDirect,\n dev: inDev && !inProd,\n optional: inOpt && !inProd && !inDev,\n resolved: entry.resolution,\n integrity: entry.checksum,\n });\n }\n return instances;\n}\n\n// ---------- shared ----------\n\n/**\n * \"lodash@^4.17.20\" -> { name: \"lodash\", selector: \"^4.17.20\" }\n * \"@scope/foo@^1.0.0\" -> { name: \"@scope/foo\", selector: \"^1.0.0\" }\n * Berry: \"lodash@npm:^4.17.20\" -> { name: \"lodash\", selector: \"^4.17.20\" }\n */\nexport function parseYarnSpec(spec: string): { name: string; selector: string } {\n const startSearch = spec.startsWith(\"@\") ? 1 : 0;\n const atIdx = spec.indexOf(\"@\", startSearch);\n if (atIdx <= 0) return { name: spec, selector: \"\" };\n const name = spec.slice(0, atIdx);\n let selector = spec.slice(atIdx + 1);\n if (selector.startsWith(\"npm:\")) selector = selector.slice(4);\n return { name, selector };\n}\n\nfunction uniq(values: string[]): string[] {\n return Array.from(new Set(values));\n}\n","export type Severity = \"critical\" | \"high\" | \"moderate\" | \"low\" | \"unknown\";\n\nexport type Ecosystem = \"npm\";\n\nexport type FindingType =\n | \"vulnerability\"\n | \"malware\"\n | \"risk-signal\"\n | \"integrity\";\n\nexport const SEVERITY_RANK: Record<Severity, number> = {\n critical: 4,\n high: 3,\n moderate: 2,\n low: 1,\n unknown: 0,\n};\n\nexport interface PackageInstance {\n name: string;\n version: string;\n ecosystem: Ecosystem;\n /** Path within the lockfile's `packages` map (e.g. \"node_modules/foo\"). */\n path: string;\n direct: boolean;\n dev: boolean;\n optional: boolean;\n resolved?: string;\n integrity?: string;\n}\n\nexport interface Finding {\n id: string;\n source: \"osv\";\n type: FindingType;\n severity: Severity;\n packageName: string;\n installedVersion: string;\n summary: string;\n url?: string;\n fixedVersions: string[];\n affectedPaths: string[];\n}\n\nexport interface ScanError {\n message: string;\n cause?: string;\n}\n\nexport interface ScanResult {\n scannedAt: string;\n packagesScanned: number;\n findings: Finding[];\n summary: Record<Severity, number>;\n errors: ScanError[];\n}\n\nexport interface ScanProjectOptions {\n cwd?: string;\n lockfile?: string;\n includeDev?: boolean;\n prodOnly?: boolean;\n cache?: boolean;\n fetchImpl?: typeof fetch;\n}\n\nexport interface ScanLockfileOptions {\n lockfilePath: string;\n includeDev?: boolean;\n prodOnly?: boolean;\n fetchImpl?: typeof fetch;\n}\n\nexport type FailOnLevel = Severity | \"none\";\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nexport interface PmCommand {\n /** Binary to spawn, e.g. \"pnpm\". */\n bin: string;\n /** Argv to spawn it with. */\n args: string[];\n}\n\nexport interface DetectOptions {\n /** Override detection. */\n override?: PackageManager;\n /** Project directory. Defaults to cwd. */\n cwd?: string;\n}\n\nconst LOCKFILES: Array<{ file: string; pm: PackageManager }> = [\n { file: \"pnpm-lock.yaml\", pm: \"pnpm\" },\n { file: \"yarn.lock\", pm: \"yarn\" },\n { file: \"bun.lockb\", pm: \"bun\" },\n { file: \"bun.lock\", pm: \"bun\" },\n { file: \"package-lock.json\", pm: \"npm\" },\n { file: \"npm-shrinkwrap.json\", pm: \"npm\" },\n];\n\nexport function detectPackageManager(opts: DetectOptions = {}): PackageManager {\n if (opts.override) return opts.override;\n const cwd = opts.cwd ?? process.cwd();\n\n const fromField = readPackageManagerField(cwd);\n if (fromField) return fromField;\n\n for (const { file, pm } of LOCKFILES) {\n if (existsSync(join(cwd, file))) return pm;\n }\n return \"npm\";\n}\n\nfunction readPackageManagerField(cwd: string): PackageManager | undefined {\n const pkgPath = join(cwd, \"package.json\");\n if (!existsSync(pkgPath)) return undefined;\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as {\n packageManager?: string;\n };\n if (typeof pkg.packageManager !== \"string\") return undefined;\n const name = pkg.packageManager.split(\"@\")[0];\n if (name === \"npm\" || name === \"pnpm\" || name === \"yarn\" || name === \"bun\") {\n return name;\n }\n } catch {\n // Malformed package.json : fall back to lockfile detection.\n }\n return undefined;\n}\n\n/**\n * Build the argv to add packages with the chosen package manager.\n * `flags` are user-supplied PM flags (e.g. -D, --save-exact) preserved as-is.\n */\nexport function buildAddCommand(\n pm: PackageManager,\n packages: string[],\n flags: string[],\n): PmCommand {\n switch (pm) {\n case \"npm\":\n return { bin: \"npm\", args: [\"install\", ...flags, ...packages] };\n case \"pnpm\":\n return { bin: \"pnpm\", args: [\"add\", ...flags, ...packages] };\n case \"yarn\":\n return { bin: \"yarn\", args: [\"add\", ...flags, ...packages] };\n case \"bun\":\n return { bin: \"bun\", args: [\"add\", ...flags, ...packages] };\n }\n}\n\nexport function buildInstallCommand(\n pm: PackageManager,\n flags: string[],\n): PmCommand {\n return { bin: pm, args: [\"install\", ...flags] };\n}\n\nexport function buildRemoveCommand(\n pm: PackageManager,\n packages: string[],\n flags: string[],\n): PmCommand {\n switch (pm) {\n case \"npm\":\n return { bin: \"npm\", args: [\"uninstall\", ...flags, ...packages] };\n case \"pnpm\":\n return { bin: \"pnpm\", args: [\"remove\", ...flags, ...packages] };\n case \"yarn\":\n return { bin: \"yarn\", args: [\"remove\", ...flags, ...packages] };\n case \"bun\":\n return { bin: \"bun\", args: [\"remove\", ...flags, ...packages] };\n }\n}\n","import { spawn } from \"node:child_process\";\nimport type { PmCommand } from \"./pm-detect.js\";\n\nexport interface RunOptions {\n cwd?: string;\n}\n\n/**\n * Spawn the package manager with stdio inherited so the user sees the live\n * install output. Resolves with the PM's exit code.\n */\nexport function runPackageManager(\n cmd: PmCommand,\n opts: RunOptions = {},\n): Promise<number> {\n return new Promise((resolve, reject) => {\n const child = spawn(cmd.bin, cmd.args, {\n cwd: opts.cwd,\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => resolve(code ?? 0));\n });\n}\n","export interface ParsedSpec {\n /** Original argv token, preserved so we can hand it back to the package manager. */\n raw: string;\n /** Bare package name, e.g. \"next\" or \"@types/node\". */\n name: string;\n /**\n * Whatever followed the \"@\" separator: an exact version, a semver range,\n * or a dist-tag like \"latest\" / \"next\". Undefined when the user passed only\n * the package name.\n */\n requested?: string;\n /** Specs we cannot meaningfully scan (git, tarball, file, url, alias). */\n unsupported?: UnsupportedReason;\n}\n\nexport type UnsupportedReason =\n | \"git\"\n | \"url\"\n | \"file\"\n | \"alias\"\n | \"workspace\"\n | \"invalid\";\n\nconst URL_PROTOCOLS = [\"http:\", \"https:\", \"git:\", \"git+ssh:\", \"git+https:\", \"git+http:\"];\n\nexport function parseSpec(raw: string): ParsedSpec {\n const trimmed = raw.trim();\n if (trimmed === \"\") {\n return { raw, name: \"\", unsupported: \"invalid\" };\n }\n\n if (trimmed.startsWith(\"file:\")) return { raw, name: trimmed, unsupported: \"file\" };\n if (trimmed.startsWith(\"workspace:\")) {\n return { raw, name: trimmed, unsupported: \"workspace\" };\n }\n if (URL_PROTOCOLS.some((p) => trimmed.startsWith(p))) {\n const reason = trimmed.includes(\"git\") ? \"git\" : \"url\";\n return { raw, name: trimmed, unsupported: reason };\n }\n // npm aliases: \"alias@npm:real-pkg@1.0\". We can't reliably gate these in v1.\n if (/^[^@/].*@npm:/.test(trimmed) || /^@[^/]+\\/[^@]+@npm:/.test(trimmed)) {\n return { raw, name: trimmed, unsupported: \"alias\" };\n }\n\n // Scoped: \"@scope/name\" or \"@scope/name@version\".\n if (trimmed.startsWith(\"@\")) {\n const slash = trimmed.indexOf(\"/\");\n if (slash === -1) return { raw, name: trimmed, unsupported: \"invalid\" };\n const rest = trimmed.slice(slash + 1);\n const at = rest.indexOf(\"@\");\n if (at === -1) {\n return { raw, name: trimmed };\n }\n const subname = rest.slice(0, at);\n const requested = rest.slice(at + 1);\n if (subname === \"\" || requested === \"\") {\n return { raw, name: trimmed, unsupported: \"invalid\" };\n }\n return { raw, name: `${trimmed.slice(0, slash)}/${subname}`, requested };\n }\n\n const at = trimmed.indexOf(\"@\");\n if (at === -1) return { raw, name: trimmed };\n const name = trimmed.slice(0, at);\n const requested = trimmed.slice(at + 1);\n if (name === \"\" || requested === \"\") {\n return { raw, name: trimmed, unsupported: \"invalid\" };\n }\n return { raw, name, requested };\n}\n\n/**\n * Splits an argv list into recognized package specs and forwarded flags.\n * Anything starting with \"-\" is treated as a flag and preserved untouched.\n */\nexport function partitionArgs(args: string[]): {\n specs: ParsedSpec[];\n flags: string[];\n} {\n const specs: ParsedSpec[] = [];\n const flags: string[] = [];\n for (const arg of args) {\n if (arg.startsWith(\"-\")) {\n flags.push(arg);\n continue;\n }\n specs.push(parseSpec(arg));\n }\n return { specs, flags };\n}\n","const REGISTRY_URL = \"https://registry.npmjs.org\";\nconst REQUEST_TIMEOUT_MS = 15_000;\n\nexport interface ResolveDeps {\n fetchImpl?: typeof fetch;\n registryUrl?: string;\n}\n\nexport interface ResolvedVersion {\n /** Concrete version we'll hand to OSV. */\n version: string;\n /**\n * How we picked it: \"exact\" (user pinned), \"dist-tag\" (latest/next/etc),\n * or \"fallback-latest\" (we couldn't resolve a range so we scanned latest).\n */\n source: \"exact\" | \"dist-tag\" | \"fallback-latest\";\n /** Set when source !== \"exact\" : what the user asked for. */\n requested?: string;\n}\n\ninterface PackumentDistTags {\n latest?: string;\n [tag: string]: string | undefined;\n}\n\ninterface Packument {\n name?: string;\n \"dist-tags\"?: PackumentDistTags;\n versions?: Record<string, unknown>;\n}\n\nconst EXACT_VERSION_RE = /^\\d+\\.\\d+\\.\\d+(?:[-+][\\w.+-]+)?$/;\nconst RANGE_CHARS_RE = /[\\^~><=|\\s*x]/i;\n\n/**\n * Resolve a user-supplied spec to a concrete version we can query OSV with.\n *\n * Strategy (v1):\n * - no version requested → dist-tags.latest\n * - exact version (1.2.3) → use as-is, verified to exist\n * - dist-tag (latest/next/beta) → dist-tags[tag], or fall back to latest\n * - semver range (^1, >=2) → dist-tags.latest with source=\"fallback-latest\"\n *\n * The fallback case is a known limitation: the installed version may differ\n * from what we scanned. The orchestrator surfaces this in its report.\n */\nexport async function resolveVersion(\n name: string,\n requested: string | undefined,\n deps: ResolveDeps = {},\n): Promise<ResolvedVersion> {\n const fetchImpl = deps.fetchImpl ?? fetch;\n const registry = deps.registryUrl ?? REGISTRY_URL;\n const packument = await fetchPackument(fetchImpl, registry, name);\n\n const distTags = packument[\"dist-tags\"] ?? {};\n const latest = distTags.latest;\n\n if (!requested) {\n if (!latest) {\n throw new VersionResolveError(\n `Package ${name} has no \"latest\" dist-tag in the registry.`,\n );\n }\n return { version: latest, source: \"dist-tag\", requested: \"latest\" };\n }\n\n if (EXACT_VERSION_RE.test(requested)) {\n if (packument.versions && !packument.versions[requested]) {\n throw new VersionResolveError(\n `Version ${requested} of ${name} is not published.`,\n );\n }\n return { version: requested, source: \"exact\" };\n }\n\n if (!RANGE_CHARS_RE.test(requested) && distTags[requested]) {\n return {\n version: distTags[requested] as string,\n source: \"dist-tag\",\n requested,\n };\n }\n\n if (!latest) {\n throw new VersionResolveError(\n `Cannot resolve ${name}@${requested}: no \"latest\" dist-tag available to fall back on.`,\n );\n }\n return { version: latest, source: \"fallback-latest\", requested };\n}\n\nexport class VersionResolveError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"VersionResolveError\";\n }\n}\n\nasync function fetchPackument(\n fetchImpl: typeof fetch,\n registry: string,\n name: string,\n): Promise<Packument> {\n const url = `${registry.replace(/\\/$/, \"\")}/${encodePackageName(name)}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n const res = await fetchImpl(url, {\n signal: controller.signal,\n headers: { accept: \"application/json\" },\n });\n if (res.status === 404) {\n throw new VersionResolveError(`Package ${name} not found in registry.`);\n }\n if (!res.ok) {\n throw new VersionResolveError(\n `Registry ${res.status} for ${name}: ${res.statusText}`,\n );\n }\n return (await res.json()) as Packument;\n } finally {\n clearTimeout(timer);\n }\n}\n\nfunction encodePackageName(name: string): string {\n // Scoped names: \"@scope/name\" → \"@scope%2Fname\"\n if (name.startsWith(\"@\")) {\n const slash = name.indexOf(\"/\");\n if (slash !== -1) {\n return `${encodeURIComponent(name.slice(0, slash))}%2F${encodeURIComponent(name.slice(slash + 1))}`;\n }\n }\n return encodeURIComponent(name);\n}\n","import type { ScanResult } from \"../types.js\";\n\nexport function reportJson(result: ScanResult): string {\n return JSON.stringify(result, null, 2);\n}\n","import kleur from \"kleur\";\nimport {\n type Finding,\n type ScanResult,\n type Severity,\n SEVERITY_RANK,\n} from \"../types.js\";\nimport { renderBanner } from \"./banner.js\";\n\nexport type TableView = \"grouped\" | \"details\" | \"summary\";\n\nexport interface ReportTableOptions {\n /** @deprecated use `view` instead */\n details?: boolean;\n view?: TableView;\n /**\n * When true, renders a boxed `trawly` nameplate at the top in place of the\n * plain `trawly: …` header. CLI sets this only when stdout is a TTY so that\n * piped/CI output stays log-parser friendly.\n */\n brand?: boolean;\n}\n\nconst SEVERITY_COLOR: Record<Severity, (s: string) => string> = {\n critical: (s) => kleur.bold().red(s),\n high: (s) => kleur.red(s),\n moderate: (s) => kleur.yellow(s),\n low: (s) => kleur.cyan(s),\n unknown: (s) => kleur.gray(s),\n};\n\nconst SEVERITY_ORDER: Severity[] = [\n \"critical\",\n \"high\",\n \"moderate\",\n \"low\",\n \"unknown\",\n];\n\ninterface PackageGroup {\n packageName: string;\n installedVersion: string;\n topSeverity: Severity;\n counts: Record<Severity, number>;\n findings: Finding[];\n recommendedFix: string | null;\n}\n\nexport function reportTable(\n result: ScanResult,\n options: ReportTableOptions = {},\n): string {\n const view: TableView = options.view ?? (options.details ? \"details\" : \"grouped\");\n const lines: string[] = [];\n\n if (options.brand) {\n const { metricsLine, timestamp } = headerParts(result);\n lines.push(renderBanner({ metrics: metricsLine, timestamp }));\n } else {\n lines.push(kleur.bold(formatHeader(result)));\n }\n\n if (result.errors.length > 0) {\n for (const err of result.errors) {\n lines.push(\n kleur.red(`! ${err.message}${err.cause ? ` (${err.cause})` : \"\"}`),\n );\n }\n }\n\n if (result.findings.length === 0) {\n lines.push(kleur.green(\"✓ No known advisories found.\"));\n lines.push(\n kleur.gray(\n \" Note: this only checks known advisories. It cannot prove a package is safe.\",\n ),\n );\n return lines.join(\"\\n\");\n }\n\n if (view === \"summary\") {\n lines.push(formatSummary(result.summary));\n lines.push(reminder());\n return lines.join(\"\\n\");\n }\n\n lines.push(\"\");\n lines.push(formatSummary(result.summary));\n lines.push(\"\");\n\n if (view === \"details\") {\n lines.push(formatDetailRows(sortFindings(result.findings)));\n } else {\n const groups = groupByPackage(result.findings);\n lines.push(formatGroupedRows(groups));\n lines.push(\"\");\n lines.push(\n kleur.gray(\"Run `trawly scan --details` to see individual advisories.\"),\n );\n }\n\n lines.push(\"\");\n lines.push(reminder());\n return lines.join(\"\\n\");\n}\n\nfunction formatHeader(result: ScanResult): string {\n const { metricsLine, timestamp } = headerParts(result);\n return `trawly: ${metricsLine} (${timestamp})`;\n}\n\nfunction headerParts(result: ScanResult): {\n metricsLine: string;\n timestamp: string;\n} {\n const vulnerable = new Set(\n result.findings.map((f) => `${f.packageName}@${f.installedVersion}`),\n ).size;\n const advisories = result.findings.length;\n const metricsLine = [\n `${result.packagesScanned} packages`,\n `${vulnerable} vulnerable`,\n `${advisories} ${advisories === 1 ? \"advisory\" : \"advisories\"}`,\n ].join(\" · \");\n return { metricsLine, timestamp: result.scannedAt };\n}\n\nfunction formatSummary(summary: ScanResult[\"summary\"]): string {\n const parts: string[] = [];\n for (const sev of SEVERITY_ORDER) {\n const count = summary[sev];\n if (count === 0) continue;\n parts.push(SEVERITY_COLOR[sev](`${sev}: ${count}`));\n }\n if (parts.length === 0) return kleur.green(\"No findings.\");\n return `Findings : ${parts.join(\" \")}`;\n}\n\nfunction reminder(): string {\n return kleur.gray(\n \"Reminder: trawly reports known advisories only. Absence of findings is not proof of safety.\",\n );\n}\n\nfunction sortFindings(findings: Finding[]): Finding[] {\n return [...findings].sort((a, b) => {\n const sev = SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity];\n if (sev !== 0) return sev;\n const name = a.packageName.localeCompare(b.packageName);\n if (name !== 0) return name;\n return a.id.localeCompare(b.id);\n });\n}\n\nfunction groupByPackage(findings: Finding[]): PackageGroup[] {\n const map = new Map<string, PackageGroup>();\n for (const f of findings) {\n const key = `${f.packageName}@${f.installedVersion}`;\n let group = map.get(key);\n if (!group) {\n group = {\n packageName: f.packageName,\n installedVersion: f.installedVersion,\n topSeverity: f.severity,\n counts: { critical: 0, high: 0, moderate: 0, low: 0, unknown: 0 },\n findings: [],\n recommendedFix: null,\n };\n map.set(key, group);\n }\n group.findings.push(f);\n group.counts[f.severity] += 1;\n if (SEVERITY_RANK[f.severity] > SEVERITY_RANK[group.topSeverity]) {\n group.topSeverity = f.severity;\n }\n }\n\n for (const group of map.values()) {\n group.recommendedFix = pickRecommendedFix(group.findings);\n }\n\n return [...map.values()].sort((a, b) => {\n const sev = SEVERITY_RANK[b.topSeverity] - SEVERITY_RANK[a.topSeverity];\n if (sev !== 0) return sev;\n const totalA = a.findings.length;\n const totalB = b.findings.length;\n if (totalA !== totalB) return totalB - totalA;\n return a.packageName.localeCompare(b.packageName);\n });\n}\n\nfunction formatGroupedRows(groups: PackageGroup[]): string {\n const rows: string[][] = [\n [\"PACKAGE\", \"VERSION\", \"SEVERITY\", \"FIX\"],\n ];\n for (const g of groups) {\n rows.push([\n g.packageName,\n g.installedVersion,\n formatSeverityCounts(g.counts),\n g.recommendedFix ? `>=${g.recommendedFix}` : \":\",\n ]);\n }\n return renderTable(rows, (rowIdx, _row, cells) => {\n if (rowIdx === 0) return kleur.bold().underline(cells.join(\" \"));\n return cells.join(\" \");\n });\n}\n\nfunction formatDetailRows(findings: Finding[]): string {\n const rows: string[][] = [\n [\"SEV\", \"PACKAGE\", \"VERSION\", \"ID\", \"FIXED IN\", \"SUMMARY\"],\n ];\n for (const f of findings) {\n rows.push([\n f.severity,\n f.packageName,\n f.installedVersion,\n f.id,\n f.fixedVersions.length ? f.fixedVersions.join(\", \") : \":\",\n truncate(f.summary, 70),\n ]);\n }\n return renderTable(rows, (rowIdx, row, cells) => {\n if (rowIdx === 0) return kleur.bold().underline(cells.join(\" \"));\n const sev = row[0] as Severity;\n const colorize = SEVERITY_COLOR[sev] ?? ((s: string) => s);\n cells[0] = colorize(cells[0]!);\n return cells.join(\" \");\n });\n}\n\nfunction formatSeverityCounts(counts: Record<Severity, number>): string {\n const parts: string[] = [];\n for (const sev of SEVERITY_ORDER) {\n const n = counts[sev];\n if (n === 0) continue;\n parts.push(SEVERITY_COLOR[sev](`${n} ${sev}`));\n }\n return parts.join(\", \");\n}\n\nfunction renderTable(\n rows: string[][],\n format: (rowIdx: number, row: string[], cells: string[]) => string,\n): string {\n const widths = rows[0]!.map((_, col) =>\n Math.max(...rows.map((r) => visibleLength(r[col]!))),\n );\n return rows\n .map((row, i) => {\n const cells = row.map((cell, col) => padEndVisible(cell, widths[col]!));\n return format(i, row, cells);\n })\n .join(\"\\n\");\n}\n\n/**\n * Pick the highest semver-ish value across all fixedVersions in the group.\n * Picking the max guarantees the upgrade clears every known advisory; users\n * can drop into `--details` if they want to evaluate alternative fix lines\n * (e.g. staying on a previous major).\n */\nfunction pickRecommendedFix(findings: Finding[]): string | null {\n const candidates: string[] = [];\n for (const f of findings) {\n for (const v of f.fixedVersions) candidates.push(v);\n }\n if (candidates.length === 0) return null;\n const unique = [...new Set(candidates)];\n unique.sort(compareSemver);\n return unique[unique.length - 1] ?? null;\n}\n\nfunction compareSemver(a: string, b: string): number {\n const pa = parseSemverParts(a);\n const pb = parseSemverParts(b);\n for (let i = 0; i < 3; i++) {\n const diff = (pa[i] ?? 0) - (pb[i] ?? 0);\n if (diff !== 0) return diff;\n }\n return a.localeCompare(b);\n}\n\nfunction parseSemverParts(v: string): number[] {\n const m = v.match(/(\\d+)\\.(\\d+)\\.(\\d+)/);\n if (!m) return [0, 0, 0];\n return [Number(m[1]), Number(m[2]), Number(m[3])];\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return `${s.slice(0, max - 1)}…`;\n}\n\n// kleur wraps strings in ANSI escape codes; padEnd needs the visible width.\nconst ANSI_RE = /\\u001B\\[[0-9;]*m/g;\nfunction visibleLength(s: string): number {\n return s.replace(ANSI_RE, \"\").length;\n}\nfunction padEndVisible(s: string, width: number): string {\n const pad = Math.max(0, width - visibleLength(s));\n return s + \" \".repeat(pad);\n}\n","import kleur from \"kleur\";\n\nexport interface BannerProps {\n /** First content row, e.g. \"164 packages · 2 vulnerable · 2 advisories\". */\n metrics: string;\n /** Second content row, typically a scannedAt ISO timestamp. */\n timestamp: string;\n}\n\nconst BORDER = {\n tl: \"┌\",\n tr: \"┐\",\n bl: \"└\",\n br: \"┘\",\n h: \"─\",\n v: \"│\",\n} as const;\n\nconst TITLE = \"trawly\";\nconst SIDE_PAD = 1; // single space between │ and content\nconst MIN_TITLE_FILLER = 4; // ensure at least \"────\" after `─ trawly `\n\nexport function renderBanner(props: BannerProps): string {\n const contentRows = [props.metrics, props.timestamp];\n const titleSegment = ` ${TITLE} `; // \" trawly \"\n const minTitleWidth = 1 + titleSegment.length + MIN_TITLE_FILLER; // ─ + \" trawly \" + ────\n\n const innerWidth = Math.max(\n ...contentRows.map((r) => r.length + SIDE_PAD * 2),\n minTitleWidth,\n );\n\n const top = renderTop(innerWidth);\n const bottom = renderBottom(innerWidth);\n const metricsLine = renderRow(innerWidth, props.metrics, kleur.bold);\n const timestampLine = renderRow(innerWidth, props.timestamp, kleur.gray);\n\n return [top, metricsLine, timestampLine, bottom].join(\"\\n\");\n}\n\nfunction renderTop(innerWidth: number): string {\n const titleSegment = ` ${kleur.bold().cyan(TITLE)} `;\n const titleVisibleLen = TITLE.length + 2; // bold/cyan don't add visible chars\n const fillerCount = innerWidth - 1 - titleVisibleLen; // -1 for the leading \"─\"\n return (\n kleur.gray(BORDER.tl) +\n kleur.gray(BORDER.h) +\n titleSegment +\n kleur.gray(BORDER.h.repeat(Math.max(MIN_TITLE_FILLER, fillerCount))) +\n kleur.gray(BORDER.tr)\n );\n}\n\nfunction renderBottom(innerWidth: number): string {\n return kleur.gray(`${BORDER.bl}${BORDER.h.repeat(innerWidth)}${BORDER.br}`);\n}\n\nfunction renderRow(\n innerWidth: number,\n content: string,\n colorize: (s: string) => string,\n): string {\n const fill = Math.max(0, innerWidth - SIDE_PAD * 2 - content.length);\n return (\n kleur.gray(BORDER.v) +\n \" \".repeat(SIDE_PAD) +\n colorize(content) +\n \" \".repeat(fill + SIDE_PAD) +\n kleur.gray(BORDER.v)\n );\n}\n"],"mappings":"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","names":["kleur","existsSync","resolve","join","readFileSync","resolve","parsed","readFileSync","resolve","yaml","resolve","existsSync","join","existsSync","readFileSync","join","resolve","at","requested","REQUEST_TIMEOUT_MS","kleur","kleur","kleur","truncate","kleur"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -74,6 +74,17 @@ declare function meetsThreshold(findings: Finding[], threshold: Severity | "none
|
|
|
74
74
|
*/
|
|
75
75
|
declare function parseNpmPackageLock(filePath: string): PackageInstance[];
|
|
76
76
|
|
|
77
|
+
declare function parsePnpmLock(filePath: string): PackageInstance[];
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Parse a yarn lockfile (classic v1 or berry v2+) and return one
|
|
81
|
+
* PackageInstance per resolved entry.
|
|
82
|
+
*
|
|
83
|
+
* Direct/dev flags are inferred by reading the sibling package.json,
|
|
84
|
+
* since yarn lockfiles don't carry that information themselves.
|
|
85
|
+
*/
|
|
86
|
+
declare function parseYarnLock(filePath: string): PackageInstance[];
|
|
87
|
+
|
|
77
88
|
interface OsvQueryDeps {
|
|
78
89
|
fetchImpl?: typeof fetch;
|
|
79
90
|
}
|
|
@@ -91,4 +102,4 @@ declare function dedupeForQuery(packages: PackageInstance[]): UniquePackage[];
|
|
|
91
102
|
*/
|
|
92
103
|
declare function queryOsv(packages: PackageInstance[], deps?: OsvQueryDeps): Promise<Finding[]>;
|
|
93
104
|
|
|
94
|
-
export { type Ecosystem, type FailOnLevel, type Finding, type FindingType, type PackageInstance, SEVERITY_RANK, type ScanError, ScanInputError, type ScanLockfileOptions, type ScanProjectOptions, type ScanResult, type Severity, compareFindings, dedupeForQuery, meetsThreshold, parseNpmPackageLock, queryOsv, scanLockfile, scanProject, summarize };
|
|
105
|
+
export { type Ecosystem, type FailOnLevel, type Finding, type FindingType, type PackageInstance, SEVERITY_RANK, type ScanError, ScanInputError, type ScanLockfileOptions, type ScanProjectOptions, type ScanResult, type Severity, compareFindings, dedupeForQuery, meetsThreshold, parseNpmPackageLock, parsePnpmLock, parseYarnLock, queryOsv, scanLockfile, scanProject, summarize };
|