dep-oracle 1.2.0 → 1.2.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/logger.ts","../src/parsers/npm.ts","../src/parsers/base.ts","../src/parsers/schema.ts","../src/parsers/python.ts","../src/cache/store.ts","../src/collectors/orchestrator.ts","../src/collectors/base.ts","../src/collectors/registry.ts","../src/collectors/github.ts","../src/collectors/security.ts","../src/collectors/funding.ts","../src/collectors/popularity.ts","../src/collectors/license.ts","../src/analyzers/trust-score.ts","../src/analyzers/zombie-detector.ts","../src/analyzers/blast-radius.ts","../src/analyzers/typosquat-registry.ts","../src/analyzers/typosquat.ts","../src/analyzers/migration-advisor.ts"],"sourcesContent":["import chalk from \"chalk\";\n\n// ---------------------------------------------------------------------------\n// Configuration\n// ---------------------------------------------------------------------------\n\nlet _verbose = false;\n\n/**\n * Enable or disable verbose (info-level) output.\n *\n * When verbose is off (default), only warn and error messages are printed.\n * Debug messages additionally require `DEP_ORACLE_DEBUG` to be set.\n */\nexport function setVerbose(enabled: boolean): void {\n _verbose = enabled;\n}\n\nexport function isVerbose(): boolean {\n return _verbose;\n}\n\n/**\n * Check whether debug output is enabled via the DEP_ORACLE_DEBUG env var.\n *\n * Any truthy value (\"1\", \"true\", \"yes\") enables debug logging.\n */\nexport function isDebug(): boolean {\n const val = process.env.DEP_ORACLE_DEBUG;\n if (!val) return false;\n return [\"1\", \"true\", \"yes\"].includes(val.toLowerCase());\n}\n\n// ---------------------------------------------------------------------------\n// Formatting helpers\n// ---------------------------------------------------------------------------\n\nfunction timestamp(): string {\n return new Date().toISOString().slice(11, 23); // HH:MM:SS.mmm\n}\n\nfunction formatMessage(level: string, colorFn: (s: string) => string, msg: string): string {\n return `${chalk.dim(timestamp())} ${colorFn(level.padEnd(5))} ${msg}`;\n}\n\n// ---------------------------------------------------------------------------\n// Logger\n// ---------------------------------------------------------------------------\n\n/**\n * Structured logger for dep-oracle.\n *\n * - `debug`: gray, only printed when `DEP_ORACLE_DEBUG` is set\n * - `info`: blue, only printed when verbose mode is enabled or `DEP_ORACLE_DEBUG` is set\n * - `warn`: yellow, always printed\n * - `error`: red, always printed\n *\n * All output goes to stderr so it never contaminates piped JSON or table output.\n */\nexport const logger = {\n debug(msg: string): void {\n if (!isDebug()) return;\n process.stderr.write(formatMessage(\"DEBUG\", chalk.gray, chalk.gray(msg)) + \"\\n\");\n },\n\n info(msg: string): void {\n if (!_verbose && !isDebug()) return;\n process.stderr.write(formatMessage(\"INFO\", chalk.blue, msg) + \"\\n\");\n },\n\n warn(msg: string): void {\n process.stderr.write(formatMessage(\"WARN\", chalk.yellow, msg) + \"\\n\");\n },\n\n error(msg: string): void {\n process.stderr.write(formatMessage(\"ERROR\", chalk.red, msg) + \"\\n\");\n },\n} as const;\n\n/**\n * Create a child logger that prefixes every message with a label.\n *\n * Useful for per-module or per-collector logging:\n * ```ts\n * const log = createLogger(\"npm-collector\");\n * log.info(\"fetching registry data\"); // => 12:34:56.789 INFO [npm-collector] fetching registry data\n * ```\n */\nexport function createLogger(label: string) {\n const prefix = chalk.dim(`[${label}]`);\n return {\n debug(msg: string): void {\n logger.debug(`${prefix} ${msg}`);\n },\n info(msg: string): void {\n logger.info(`${prefix} ${msg}`);\n },\n warn(msg: string): void {\n logger.warn(`${prefix} ${msg}`);\n },\n error(msg: string): void {\n logger.error(`${prefix} ${msg}`);\n },\n } as const;\n}\n","import { readFile, access } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { BaseParser } from \"./base.js\";\nimport {\n type DependencyTree,\n createDependencyTree,\n createDependencyNode,\n} from \"./schema.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readJson<T = unknown>(path: string): Promise<T> {\n const raw = await readFile(path, \"utf-8\");\n return JSON.parse(raw) as T;\n}\n\nasync function readText(path: string): Promise<string> {\n return readFile(path, \"utf-8\");\n}\n\n/** Merge a record of { name: versionSpec } into the nodes map. */\nfunction addDirectDeps(\n tree: DependencyTree,\n deps: Record<string, string> | undefined,\n): void {\n if (!deps) return;\n for (const [name, version] of Object.entries(deps)) {\n const key = `${name}@${version}`;\n if (tree.nodes.has(key)) continue;\n tree.nodes.set(\n key,\n createDependencyNode({ name, version, registry: \"npm\", depth: 0, isDirect: true, parent: null }),\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Lock-file parsers\n// ---------------------------------------------------------------------------\n\n/**\n * Parse package-lock.json v2/v3 \"packages\" field.\n *\n * The top-level key \"\" is the project root — skip it. Every other key is of\n * the form \"node_modules/<name>\" (possibly nested).\n */\nfunction parsePackageLock(\n lockData: PackageLockJson,\n directNames: Set<string>,\n tree: DependencyTree,\n): void {\n const packages = lockData.packages ?? {};\n\n for (const [pkgPath, meta] of Object.entries(packages)) {\n // Skip the root entry\n if (pkgPath === \"\") continue;\n\n // Extract the package name from the path.\n // e.g. \"node_modules/express\" -> \"express\"\n // \"node_modules/@scope/pkg\" -> \"@scope/pkg\"\n // \"node_modules/a/node_modules/b\" -> \"b\"\n const segments = pkgPath.split(\"node_modules/\");\n const name = segments[segments.length - 1];\n if (!name) continue;\n\n const version = meta.version ?? \"unknown\";\n const depth = segments.length - 1; // 1 = direct level, 2+ = transitive\n const isDirect = depth === 1 && directNames.has(name);\n\n const key = `${name}@${version}`;\n if (tree.nodes.has(key)) continue;\n\n tree.nodes.set(\n key,\n createDependencyNode({\n name,\n version,\n registry: \"npm\",\n depth: isDirect ? 0 : depth,\n isDirect,\n parent: isDirect ? null : inferParent(pkgPath),\n }),\n );\n }\n}\n\n/** Extract the parent package name from a nested node_modules path. */\nfunction inferParent(pkgPath: string): string | null {\n // \"node_modules/a/node_modules/b\" -> parent is \"a\"\n const parts = pkgPath.split(\"/node_modules/\");\n if (parts.length < 2) return null;\n // The second-to-last segment is the parent\n return parts.length >= 2 ? parts[parts.length - 2] : null;\n}\n\n/**\n * Parse a yarn.lock (v1) flat format.\n *\n * Each block looks like:\n * ```\n * \"express@^4.18.0\":\n * version \"4.18.2\"\n * resolved \"https://...\"\n * ...\n * ```\n */\nfunction parseYarnLock(\n content: string,\n directNames: Set<string>,\n tree: DependencyTree,\n): void {\n const lines = content.split(\"\\n\");\n let currentNames: string[] = [];\n let currentVersion: string | null = null;\n\n const flush = (): void => {\n if (currentNames.length === 0 || !currentVersion) return;\n for (const rawName of currentNames) {\n // rawName is e.g. \"express@^4.18.0\" or \"@scope/pkg@~1.0.0\"\n const atIdx = rawName.lastIndexOf(\"@\");\n const name = atIdx > 0 ? rawName.slice(0, atIdx) : rawName;\n const version = currentVersion;\n const isDirect = directNames.has(name);\n const key = `${name}@${version}`;\n if (tree.nodes.has(key)) continue;\n\n tree.nodes.set(\n key,\n createDependencyNode({\n name,\n version,\n registry: \"npm\",\n depth: isDirect ? 0 : 1,\n isDirect,\n parent: null,\n }),\n );\n }\n };\n\n for (const line of lines) {\n // Skip comments and blank lines\n if (line.startsWith(\"#\") || line.trim() === \"\") continue;\n\n // Header line (no leading whitespace)\n if (!line.startsWith(\" \") && !line.startsWith(\"\\t\")) {\n flush();\n currentNames = [];\n currentVersion = null;\n\n // Parse the header: could have multiple comma-separated entries\n // e.g.: \"chalk@^4.0.0\", \"chalk@^4.1.0\":\n const cleaned = line.replace(/:$/, \"\").trim();\n const entries = cleaned.split(\",\").map((s) => s.trim().replace(/^\"|\"$/g, \"\"));\n currentNames = entries.filter(Boolean);\n continue;\n }\n\n // version field inside a block\n const versionMatch = line.match(/^\\s+version\\s+\"?([^\"]+)\"?/);\n if (versionMatch) {\n currentVersion = versionMatch[1];\n }\n }\n // Flush the last block\n flush();\n}\n\n/**\n * Parse pnpm-lock.yaml (lockfileVersion 9 format).\n *\n * The interesting section is `packages:` which is a map like:\n * /@scope/pkg@1.2.3:\n * resolution: ...\n * dependencies: ...\n *\n * In newer v9 the key format is: `<name>@<version>` (no leading slash).\n *\n * We use a lightweight regex approach to avoid pulling in a YAML parser as a\n * hard dependency — this project already has zero YAML dependencies.\n */\nfunction parsePnpmLock(\n content: string,\n directNames: Set<string>,\n tree: DependencyTree,\n): void {\n // Match lines that look like package entries under the `packages:` section.\n // Both formats:\n // /@scope/name@1.0.0: (lockfileVersion < 9)\n // @scope/name@1.0.0: (lockfileVersion 9)\n // name@1.0.0: (unscoped)\n // /name@1.0.0: (unscoped, old)\n // Lines inside a `packages:` block that start at column 2+ with an @ or letter.\n\n const lines = content.split(\"\\n\");\n let inPackages = false;\n // Track the current package context for nested dependency parsing\n let currentPackageName: string | null = null;\n let inDependencies = false;\n\n for (const line of lines) {\n const trimmed = line.trimEnd();\n\n // Detect the packages section\n if (/^packages:/.test(trimmed)) {\n inPackages = true;\n continue;\n }\n\n // If we hit another top-level key, stop\n if (inPackages && /^\\S/.test(trimmed) && !trimmed.startsWith(\" \") && !trimmed.startsWith(\"'\") && !trimmed.startsWith(\"/\")) {\n // Could be another top-level key like \"snapshots:\" or \"importers:\"\n if (!trimmed.includes(\"@\") && trimmed.endsWith(\":\")) {\n inPackages = false;\n continue;\n }\n }\n\n if (!inPackages) continue;\n\n // Package entry line (indented with 2 spaces or starts with / or quoted)\n // Patterns:\n // ' /@scope/pkg@1.0.0:'\n // ' name@1.0.0:'\n // ' @scope/name@1.0.0:'\n const pkgMatch = trimmed.match(\n /^\\s{2,4}(?:'|\")?\\/?((?:@[^/@]+\\/)?[^@:'\"]+)@([^:'\"]+)(?:'|\")?:\\s*$/,\n );\n\n if (pkgMatch) {\n const [, name, version] = pkgMatch;\n if (!name || !version) continue;\n\n currentPackageName = name;\n inDependencies = false;\n\n const isDirect = directNames.has(name);\n const key = `${name}@${version}`;\n if (tree.nodes.has(key)) continue;\n\n tree.nodes.set(\n key,\n createDependencyNode({\n name,\n version,\n registry: \"npm\",\n depth: isDirect ? 0 : 1,\n isDirect,\n parent: null,\n }),\n );\n continue;\n }\n\n // Detect \"dependencies:\" sub-block\n if (/^\\s{4,6}dependencies:/.test(trimmed)) {\n inDependencies = true;\n continue;\n }\n\n // Detect end of dependencies sub-block (less indentation or new section)\n if (inDependencies && /^\\s{4,6}\\S/.test(trimmed) && !trimmed.match(/^\\s{6,}/)) {\n inDependencies = false;\n }\n\n // Parse individual dependency lines inside a dependencies block\n if (inDependencies && currentPackageName) {\n const depMatch = trimmed.match(/^\\s{6,8}(?:'|\")?([^:'\"]+)(?:'|\")?\\s*:\\s*(?:'|\")?([^'\"]+)(?:'|\")?/);\n if (depMatch) {\n const [, depName, depVersion] = depMatch;\n if (!depName || !depVersion) continue;\n\n const cleanVersion = depVersion.trim();\n const isDirect = directNames.has(depName);\n const key = `${depName}@${cleanVersion}`;\n if (tree.nodes.has(key)) continue;\n\n tree.nodes.set(\n key,\n createDependencyNode({\n name: depName,\n version: cleanVersion,\n registry: \"npm\",\n depth: isDirect ? 0 : 2,\n isDirect,\n parent: isDirect ? null : currentPackageName,\n }),\n );\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Types for package-lock.json\n// ---------------------------------------------------------------------------\n\ninterface PackageLockJson {\n lockfileVersion?: number;\n packages?: Record<string, { version?: string; dependencies?: Record<string, string> }>;\n}\n\ninterface PackageJson {\n name?: string;\n version?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n}\n\n// ---------------------------------------------------------------------------\n// NpmParser\n// ---------------------------------------------------------------------------\n\nexport class NpmParser extends BaseParser {\n readonly name = \"npm\";\n\n async detect(dir: string): Promise<boolean> {\n return fileExists(join(dir, \"package.json\"));\n }\n\n async parse(dir: string): Promise<DependencyTree> {\n const pkgPath = join(dir, \"package.json\");\n const pkg = await readJson<PackageJson>(pkgPath);\n\n const projectName = pkg.name ?? \"unknown\";\n const tree = createDependencyTree(projectName, pkgPath);\n\n // Collect direct dependency names for reference during lock-file parsing\n const allDirect: Record<string, string> = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n const directNames = new Set(Object.keys(allDirect));\n\n // Add direct dependencies first\n addDirectDeps(tree, pkg.dependencies);\n addDirectDeps(tree, pkg.devDependencies);\n\n // Try lock files in priority order: package-lock.json > yarn.lock > pnpm-lock.yaml\n const lockPath = join(dir, \"package-lock.json\");\n const yarnPath = join(dir, \"yarn.lock\");\n const pnpmPath = join(dir, \"pnpm-lock.yaml\");\n\n if (await fileExists(lockPath)) {\n const lockData = await readJson<PackageLockJson>(lockPath);\n parsePackageLock(lockData, directNames, tree);\n } else if (await fileExists(yarnPath)) {\n const yarnContent = await readText(yarnPath);\n parseYarnLock(yarnContent, directNames, tree);\n } else if (await fileExists(pnpmPath)) {\n const pnpmContent = await readText(pnpmPath);\n parsePnpmLock(pnpmContent, directNames, tree);\n }\n // If no lock file is found, we already have direct deps from package.json\n\n // Deduplicate direct deps: when a lockfile provided resolved versions,\n // remove the version-range entries (e.g. keep \"chalk@5.6.2\", remove \"chalk@^5.3.0\").\n this.deduplicateDirectDeps(tree);\n\n // Recount totals — lock file parsing may have adjusted depths\n tree.totalDirect = 0;\n tree.totalTransitive = 0;\n for (const node of tree.nodes.values()) {\n if (node.isDirect) {\n tree.totalDirect++;\n } else {\n tree.totalTransitive++;\n }\n }\n\n return tree;\n }\n\n /**\n * When both a version-range entry (from package.json) and a resolved-version\n * entry (from lockfile) exist for the same package name, keep only the\n * resolved one.\n *\n * A version is considered \"resolved\" when it does NOT start with ^, ~, >=, etc.\n */\n private deduplicateDirectDeps(tree: DependencyTree): void {\n // Group direct deps by package name\n const byName = new Map<string, Array<{ key: string; version: string }>>();\n\n for (const [key, node] of tree.nodes.entries()) {\n if (!node.isDirect) continue;\n const list = byName.get(node.name) ?? [];\n list.push({ key, version: node.version });\n byName.set(node.name, list);\n }\n\n for (const [, entries] of byName) {\n if (entries.length <= 1) continue;\n\n // Determine which entries are version ranges\n const isRange = (v: string) => /^[~^>=<*]/.test(v) || v === 'latest';\n const resolved = entries.filter((e) => !isRange(e.version));\n const ranges = entries.filter((e) => isRange(e.version));\n\n // If we have at least one resolved version, remove all range entries\n if (resolved.length > 0 && ranges.length > 0) {\n for (const range of ranges) {\n tree.nodes.delete(range.key);\n }\n }\n }\n }\n}\n","import type { DependencyTree } from \"./schema.js\";\n\n/**\n * Abstract base class that every manifest parser must extend.\n *\n * Each parser is responsible for a single ecosystem (npm, pypi, etc.) and\n * knows how to:\n * 1. Detect whether its manifest file exists in a given directory.\n * 2. Parse that manifest (and optional lock file) into a DependencyTree.\n */\nexport abstract class BaseParser {\n /** Human-readable name used in logs and reports (e.g. \"npm\", \"python\"). */\n abstract readonly name: string;\n\n /**\n * Return `true` when the parser's manifest file(s) exist in `dir`.\n *\n * Implementations should use `fs.access` (or equivalent) and must never\n * throw — return `false` for any I/O error.\n */\n abstract detect(dir: string): Promise<boolean>;\n\n /**\n * Parse the manifest (and optional lock file) found in `dir` and return a\n * fully populated DependencyTree.\n *\n * Implementations may throw when the manifest is present but malformed.\n */\n abstract parse(dir: string): Promise<DependencyTree>;\n}\n","import { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Registry enum\n// ---------------------------------------------------------------------------\n\nexport const RegistryEnum = z.enum([\"npm\", \"pypi\"]);\nexport type Registry = z.infer<typeof RegistryEnum>;\n\n// ---------------------------------------------------------------------------\n// DependencyNode\n// ---------------------------------------------------------------------------\n\nexport const DependencyNodeSchema = z.object({\n /** Package name (e.g. \"express\", \"requests\") */\n name: z.string().min(1),\n /** Resolved or declared version string */\n version: z.string(),\n /** 0 = direct dependency, 1+ = transitive depth */\n depth: z.number().int().min(0),\n /** Convenience flag: true when depth === 0 */\n isDirect: z.boolean(),\n /** Parent package name, null for direct deps */\n parent: z.string().nullable(),\n /** Which registry this package comes from */\n registry: RegistryEnum,\n});\n\nexport type DependencyNode = z.infer<typeof DependencyNodeSchema>;\n\n// ---------------------------------------------------------------------------\n// DependencyTree\n// ---------------------------------------------------------------------------\n\nexport const DependencyTreeSchema = z.object({\n /** Project / root package name */\n root: z.string(),\n /** Absolute path to the manifest file that was parsed */\n manifest: z.string(),\n /** All resolved dependency nodes keyed by \"name@version\" */\n nodes: z.map(z.string(), DependencyNodeSchema),\n /** Count of direct dependencies (depth === 0) */\n totalDirect: z.number().int().min(0),\n /** Count of transitive dependencies (depth > 0) */\n totalTransitive: z.number().int().min(0),\n});\n\nexport type DependencyTree = z.infer<typeof DependencyTreeSchema>;\n\n// ---------------------------------------------------------------------------\n// CollectorResult<T> — generic wrapper for any data-fetching operation\n// ---------------------------------------------------------------------------\n\nexport const CollectorStatusEnum = z.enum([\"success\", \"error\", \"cached\", \"offline\"]);\nexport type CollectorStatus = z.infer<typeof CollectorStatusEnum>;\n\nexport function CollectorResultSchema<T extends z.ZodTypeAny>(dataSchema: T) {\n return z.object({\n status: CollectorStatusEnum,\n data: dataSchema.nullable(),\n error: z.string().optional(),\n collectedAt: z.string().datetime().optional(),\n });\n}\n\nexport interface CollectorResult<T> {\n status: CollectorStatus;\n data: T | null;\n error?: string;\n collectedAt?: string;\n}\n\n// ---------------------------------------------------------------------------\n// RegistryData\n// ---------------------------------------------------------------------------\n\nexport const RegistryDataSchema = z.object({\n /** Package name */\n packageName: z.string(),\n /** Resolved version string */\n version: z.string(),\n /** Short description from the registry */\n description: z.string().nullable(),\n /** ISO-8601 timestamp of the last publish, null if unknown */\n lastPublishDate: z.string().nullable(),\n /** Total number of published versions */\n versionCount: z.number().int().min(0),\n /** Deprecation message string, null if not deprecated */\n deprecated: z.string().nullable(),\n /** Downloads in the last 7 days */\n weeklyDownloads: z.number().int().min(0),\n /** SPDX license identifier from the registry */\n license: z.string().nullable(),\n /** Normalised repository URL */\n repositoryUrl: z.string().nullable(),\n});\n\nexport type RegistryData = z.infer<typeof RegistryDataSchema>;\n\n// ---------------------------------------------------------------------------\n// GitHubData\n// ---------------------------------------------------------------------------\n\nexport const GitHubDataSchema = z.object({\n /** GitHub repository owner */\n owner: z.string(),\n /** GitHub repository name */\n repo: z.string(),\n stars: z.number().int().min(0),\n forks: z.number().int().min(0),\n openIssues: z.number().int().min(0),\n /** ISO-8601 timestamp of the last repo update */\n updatedAt: z.string(),\n /** Whether the repository is archived */\n archived: z.boolean(),\n /** Default branch name */\n defaultBranch: z.string(),\n contributorCount: z.number().int().min(0),\n /** Number of commits in the last 30 days */\n recentCommitCount: z.number().int().min(0),\n /** ISO-8601 timestamp of the most recent commit, null if unknown */\n lastCommitDate: z.string().nullable(),\n /** SHA of the most recent commit, null if unknown */\n lastCommitSha: z.string().nullable(),\n /** Whether a .github/FUNDING.yml file exists */\n hasFundingYml: z.boolean(),\n});\n\nexport type GitHubData = z.infer<typeof GitHubDataSchema>;\n\n// ---------------------------------------------------------------------------\n// SecurityData\n// ---------------------------------------------------------------------------\n\nexport const VulnerabilityEntrySchema = z.object({\n id: z.string(),\n summary: z.string().nullable(),\n severity: z.enum([\"critical\", \"high\", \"medium\", \"low\", \"unknown\"]),\n published: z.string(),\n});\n\nexport type VulnerabilityEntry = z.infer<typeof VulnerabilityEntrySchema>;\n\nexport const SecurityDataSchema = z.object({\n /** Package name */\n packageName: z.string(),\n /** Resolved version string */\n version: z.string(),\n /** Total number of known vulnerabilities */\n totalVulnerabilities: z.number().int().min(0),\n /** Vulnerability counts by severity level */\n severityCounts: z.record(z.string(), z.number().int().min(0)),\n /** ISO-8601 timestamp of the most recent vulnerability, null if none */\n latestVulnDate: z.string().nullable(),\n /** Average days from disclosure to patch, null when unknown */\n averagePatchDays: z.number().nullable(),\n /** List of individual vulnerabilities */\n vulnerabilities: z.array(VulnerabilityEntrySchema),\n});\n\nexport type SecurityData = z.infer<typeof SecurityDataSchema>;\n\n// ---------------------------------------------------------------------------\n// FundingData\n// ---------------------------------------------------------------------------\n\nexport const FundingDataSchema = z.object({\n /** Package name */\n packageName: z.string(),\n /** Whether GitHub sponsors exist (via FUNDING.yml) */\n hasSponsors: z.boolean(),\n /** Whether an OpenCollective profile is active */\n hasOpenCollective: z.boolean(),\n /** Whether the npm registry \"funding\" field is set */\n hasNpmFunding: z.boolean(),\n /** OpenCollective slug, null if none */\n openCollectiveSlug: z.string().nullable(),\n /** Number of OpenCollective backers */\n openCollectiveBackers: z.number().int().min(0),\n /** Rough USD estimate of annual funding, 0 when unknown */\n estimatedAnnualFunding: z.number().min(0),\n /** Collected funding URLs from all sources */\n fundingUrls: z.array(z.string()),\n});\n\nexport type FundingData = z.infer<typeof FundingDataSchema>;\n\n// ---------------------------------------------------------------------------\n// PopularityData\n// ---------------------------------------------------------------------------\n\nexport const DownloadTrendEnum = z.enum([\"rising\", \"stable\", \"declining\"]);\nexport type DownloadTrend = z.infer<typeof DownloadTrendEnum>;\n\nexport const PopularityDataSchema = z.object({\n /** Package name */\n packageName: z.string(),\n /** Downloads in the last 7 days */\n weeklyDownloads: z.number().int().min(0),\n /** Downloads in the last 30 days */\n monthlyDownloads: z.number().int().min(0),\n /** Download trend direction */\n trend: DownloadTrendEnum,\n /** Number of packages that depend on this one */\n dependentCount: z.number().int().min(0),\n});\n\nexport type PopularityData = z.infer<typeof PopularityDataSchema>;\n\n// ---------------------------------------------------------------------------\n// LicenseData\n// ---------------------------------------------------------------------------\n\nexport const LicenseRiskEnum = z.enum([\"safe\", \"cautious\", \"risky\", \"unknown\"]);\nexport type LicenseRisk = z.infer<typeof LicenseRiskEnum>;\n\nexport const LicenseDataSchema = z.object({\n /** Package name */\n packageName: z.string(),\n /** Resolved version string */\n version: z.string(),\n /** Raw license string from the registry */\n raw: z.string().nullable(),\n /** Normalised SPDX identifier, null if unrecognised */\n spdx: z.string().nullable(),\n /** Risk classification */\n risk: LicenseRiskEnum,\n /** Whether the license is OSI-approved */\n osiApproved: z.boolean(),\n});\n\nexport type LicenseData = z.infer<typeof LicenseDataSchema>;\n\n// ---------------------------------------------------------------------------\n// TrustMetrics (each dimension scored 0-100)\n// ---------------------------------------------------------------------------\n\nconst scoreField = z.number().min(0).max(100);\n\nexport const TrustMetricsSchema = z.object({\n security: scoreField,\n maintainer: scoreField,\n activity: scoreField,\n popularity: scoreField,\n funding: scoreField,\n license: scoreField,\n});\n\nexport type TrustMetrics = z.infer<typeof TrustMetricsSchema>;\n\n// ---------------------------------------------------------------------------\n// TrustReport (per-package output of the analysis pipeline)\n// ---------------------------------------------------------------------------\n\nexport const TrustReportSchema = z.object({\n /** Package name */\n package: z.string(),\n /** Analyzed version */\n version: z.string(),\n /** Weighted overall score 0-100 */\n trustScore: scoreField,\n /** Breakdown by dimension */\n metrics: TrustMetricsSchema,\n /** True when the package shows signs of abandonment */\n isZombie: z.boolean(),\n /** Number of project files that import this package */\n blastRadius: z.number().int().min(0),\n /** Suggested replacement packages if the score is low */\n alternatives: z.array(z.string()),\n /** Download trend for quick triage */\n trend: DownloadTrendEnum,\n /** Probability (0-1) that the package name is a typosquat */\n typosquatRisk: z.number().min(0).max(1),\n});\n\nexport type TrustReport = z.infer<typeof TrustReportSchema>;\n\n// ---------------------------------------------------------------------------\n// ScanResult (top-level output of a full scan)\n// ---------------------------------------------------------------------------\n\nexport const ScanResultSchema = z.object({\n tree: DependencyTreeSchema,\n reports: z.array(TrustReportSchema),\n /** Weighted average of all package trust scores */\n overallScore: scoreField,\n /** Human-readable summary paragraph */\n summary: z.string(),\n});\n\nexport type ScanResult = z.infer<typeof ScanResultSchema>;\n\n// ---------------------------------------------------------------------------\n// Config (user-facing configuration via cosmiconfig / .dep-oraclerc etc.)\n// ---------------------------------------------------------------------------\n\nexport const ConfigSchema = z.object({\n /** Minimum trust score before a warning is emitted */\n minTrustScore: z.number().min(0).max(100).default(50),\n\n /** How long collector responses are cached, in seconds */\n cacheTtl: z.number().int().min(0).default(86_400),\n\n /** GitHub personal access token (increases rate limit) */\n githubToken: z.string().optional(),\n\n /** Packages to exclude from scanning */\n ignore: z.array(z.string()).default([]),\n\n /** Weight overrides for the trust-score dimensions (must sum to ~1) */\n weights: z\n .object({\n security: z.number().min(0).max(1).default(0.30),\n maintainer: z.number().min(0).max(1).default(0.20),\n activity: z.number().min(0).max(1).default(0.15),\n popularity: z.number().min(0).max(1).default(0.15),\n funding: z.number().min(0).max(1).default(0.10),\n license: z.number().min(0).max(1).default(0.10),\n })\n .default({}),\n\n /** Maximum concurrent network requests */\n concurrency: z.number().int().min(1).max(20).default(6),\n\n /** Registries to query */\n registries: z.array(RegistryEnum).default([\"npm\"]),\n\n /** Output format */\n outputFormat: z.enum([\"table\", \"json\", \"markdown\"]).default(\"table\"),\n\n /** Days of inactivity after which a package is considered a zombie */\n zombieThresholdDays: z.number().int().min(1).default(365),\n\n /** Enable offline mode (only use cache, never hit network) */\n offline: z.boolean().default(false),\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\n\n// ---------------------------------------------------------------------------\n// Convenience factory helpers\n// ---------------------------------------------------------------------------\n\n/** Create a DependencyNode with sensible defaults. */\nexport function createDependencyNode(\n partial: Pick<DependencyNode, \"name\" | \"version\" | \"registry\"> &\n Partial<Omit<DependencyNode, \"name\" | \"version\" | \"registry\">>,\n): DependencyNode {\n return {\n depth: 0,\n isDirect: partial.depth === undefined || partial.depth === 0,\n parent: null,\n ...partial,\n };\n}\n\n/** Create an empty DependencyTree for a project. */\nexport function createDependencyTree(\n root: string,\n manifest: string,\n): DependencyTree {\n return {\n root,\n manifest,\n nodes: new Map(),\n totalDirect: 0,\n totalTransitive: 0,\n };\n}\n\n/** Wrap a successful collector response. */\nexport function collectorSuccess<T>(data: T): CollectorResult<T> {\n return { status: \"success\", data };\n}\n\n/** Wrap a failed collector response. */\nexport function collectorError<T>(error: string): CollectorResult<T> {\n return { status: \"error\", data: null, error };\n}\n\n/** Wrap a cached collector response. */\nexport function collectorCached<T>(data: T, collectedAt: string): CollectorResult<T> {\n return { status: \"cached\", data, collectedAt };\n}\n\n/** Wrap an offline collector response. */\nexport function collectorOffline<T>(): CollectorResult<T> {\n return { status: \"offline\", data: null, error: \"Network unavailable — offline mode\" };\n}\n","import { readFile, access } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { BaseParser } from \"./base.js\";\nimport {\n type DependencyTree,\n createDependencyTree,\n createDependencyNode,\n} from \"./schema.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readText(path: string): Promise<string> {\n return readFile(path, \"utf-8\");\n}\n\nasync function readJson<T = unknown>(path: string): Promise<T> {\n const raw = await readFile(path, \"utf-8\");\n return JSON.parse(raw) as T;\n}\n\n/**\n * Normalize a Python package name according to PEP 503.\n * Replaces runs of [-_.] with a single hyphen and lowercases.\n */\nfunction normalizePyPIName(name: string): string {\n return name.toLowerCase().replace(/[-_.]+/g, \"-\");\n}\n\n/**\n * Parse a single PEP 508 dependency specifier and return (name, version).\n *\n * Handles:\n * requests==2.31.0\n * flask>=2.0,<3.0\n * django~=4.2\n * numpy\n * black[jupyter]>=23.0\n * urllib3 ; python_version >= \"3.7\"\n */\nfunction parsePep508(spec: string): { name: string; version: string } | null {\n // Strip inline comments\n const cleaned = spec.replace(/\\s+#.*$/, '').trim();\n if (!cleaned || cleaned.startsWith(\"-\")) return null;\n\n // Strip environment markers (everything after a bare \";\")\n const withoutMarkers = cleaned.split(\";\")[0].trim();\n\n // Match: name[extras](==|>=|<=|~=|!=|>|<)version(,...)\n const match = withoutMarkers.match(\n /^([A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?)(\\[.*?\\])?\\s*(.*)?$/,\n );\n if (!match) return null;\n\n const rawName = match[1];\n const versionPart = (match[4] ?? \"\").trim();\n\n // Clean version: take the full constraint string as the version\n const version = versionPart || \"*\";\n\n return {\n name: normalizePyPIName(rawName),\n version,\n };\n}\n\n// ---------------------------------------------------------------------------\n// requirements.txt parser\n// ---------------------------------------------------------------------------\n\nfunction parseRequirementsTxt(\n content: string,\n tree: DependencyTree,\n): void {\n const lines = content.split(\"\\n\");\n for (const rawLine of lines) {\n const line = rawLine.trim();\n // Skip comments, blank lines, and option lines\n if (!line || line.startsWith(\"#\") || line.startsWith(\"-\")) continue;\n\n const dep = parsePep508(line);\n if (!dep) continue;\n\n const key = `${dep.name}@${dep.version}`;\n if (tree.nodes.has(key)) continue;\n\n tree.nodes.set(\n key,\n createDependencyNode({\n name: dep.name,\n version: dep.version,\n registry: \"pypi\",\n depth: 0,\n isDirect: true,\n parent: null,\n }),\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// pyproject.toml parser (lightweight, regex-based to avoid TOML dep)\n// ---------------------------------------------------------------------------\n\n/**\n * Extract the [project.dependencies] array from pyproject.toml content.\n *\n * We use a simple state-machine approach instead of a full TOML parser to\n * keep the dependency count at zero for parsing logic.\n */\nfunction parsePyprojectDeps(content: string): string[] {\n const deps: string[] = [];\n const lines = content.split(\"\\n\");\n let inSection = false;\n let inArray = false;\n\n for (const rawLine of lines) {\n const line = rawLine.trim();\n\n // Detect [project] section's dependencies key\n if (/^\\[project\\]/.test(line)) {\n inSection = true;\n continue;\n }\n\n // Detect [tool.poetry.dependencies] section\n if (/^\\[tool\\.poetry\\.dependencies\\]/.test(line)) {\n inSection = true;\n continue;\n }\n\n // If we hit a new section header, stop\n if (inSection && /^\\[/.test(line) && !/^\\[project\\]/.test(line) && !/^\\[tool\\.poetry\\.dependencies\\]/.test(line)) {\n inSection = false;\n inArray = false;\n continue;\n }\n\n if (!inSection) continue;\n\n // Inside [project] look for `dependencies = [`\n if (/^dependencies\\s*=\\s*\\[/.test(line)) {\n inArray = true;\n // Check if entries are on the same line: dependencies = [\"foo\", \"bar\"]\n const inlineMatch = line.match(/\\[(.+)\\]/);\n if (inlineMatch) {\n const entries = inlineMatch[1]\n .split(\",\")\n .map((s) => s.trim().replace(/^\"|\"$/g, \"\").replace(/^'|'$/g, \"\"));\n deps.push(...entries.filter(Boolean));\n inArray = false;\n }\n continue;\n }\n\n // Inside the dependencies array, collect entries\n if (inArray) {\n if (line === \"]\") {\n inArray = false;\n continue;\n }\n // Each line is like \"requests>=2.28\" or 'flask~=2.0',\n const cleaned = line.replace(/,$/g, \"\").replace(/^\"|\"$/g, \"\").replace(/^'|'$/g, \"\").trim();\n if (cleaned) {\n deps.push(cleaned);\n }\n continue;\n }\n\n // Inside [tool.poetry.dependencies] entries look like:\n // requests = \"^2.28\"\n // python = \"^3.10\"\n // flask = {version = \"~2.0\", optional = true}\n if (inSection && !inArray && line.includes(\"=\") && !line.startsWith(\"[\")) {\n const eqIdx = line.indexOf(\"=\");\n const key = line.slice(0, eqIdx).trim();\n const valRaw = line.slice(eqIdx + 1).trim();\n\n // Skip the python version constraint\n if (key === \"python\") continue;\n // Skip empty or non-string values\n if (!valRaw) continue;\n\n let version = \"*\";\n // Simple string value: \"^2.28\"\n const strMatch = valRaw.match(/^\"([^\"]+)\"|^'([^']+)'/);\n if (strMatch) {\n version = strMatch[1] ?? strMatch[2] ?? \"*\";\n }\n // Inline table: {version = \"~2.0\", ...}\n const tableMatch = valRaw.match(/version\\s*=\\s*\"([^\"]+)\"/);\n if (tableMatch) {\n version = tableMatch[1];\n }\n\n deps.push(`${key}${version !== \"*\" ? version : \"\"}`);\n }\n }\n\n return deps;\n}\n\nfunction addPyprojectDeps(content: string, tree: DependencyTree): void {\n const specs = parsePyprojectDeps(content);\n for (const spec of specs) {\n const dep = parsePep508(spec);\n if (!dep) continue;\n\n const key = `${dep.name}@${dep.version}`;\n if (tree.nodes.has(key)) continue;\n\n tree.nodes.set(\n key,\n createDependencyNode({\n name: dep.name,\n version: dep.version,\n registry: \"pypi\",\n depth: 0,\n isDirect: true,\n parent: null,\n }),\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Pipfile.lock parser (transitive dependencies)\n// ---------------------------------------------------------------------------\n\ninterface PipfileLockJson {\n default?: Record<string, { version?: string }>;\n develop?: Record<string, { version?: string }>;\n}\n\nfunction parsePipfileLock(\n lockData: PipfileLockJson,\n tree: DependencyTree,\n): void {\n const directNames = new Set<string>();\n for (const node of tree.nodes.values()) {\n if (node.isDirect) {\n directNames.add(node.name);\n }\n }\n\n const sections: Array<Record<string, { version?: string }> | undefined> = [\n lockData.default,\n lockData.develop,\n ];\n\n for (const section of sections) {\n if (!section) continue;\n for (const [rawName, meta] of Object.entries(section)) {\n const name = normalizePyPIName(rawName);\n // Version in Pipfile.lock is like \"==2.31.0\"\n const version = (meta.version ?? \"*\").replace(/^==/, \"\");\n const isDirect = directNames.has(name);\n\n const key = `${name}@${version}`;\n if (tree.nodes.has(key)) continue;\n\n tree.nodes.set(\n key,\n createDependencyNode({\n name,\n version,\n registry: \"pypi\",\n depth: isDirect ? 0 : 1,\n isDirect,\n parent: null,\n }),\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// poetry.lock parser (regex-based, no TOML library)\n// ---------------------------------------------------------------------------\n\n/**\n * Parse a poetry.lock file to extract package names and versions.\n *\n * poetry.lock uses a TOML-like format with repeated `[[package]]` blocks.\n * Each block has `name = \"...\"` and `version = \"...\"` lines. We use regex\n * to split on `[[package]]` headers and extract the fields we need.\n *\n * Packages that match an already-known direct dependency (from pyproject.toml\n * or requirements.txt) are marked `isDirect: true, depth: 0`. All others are\n * treated as transitive (`depth: 1`).\n */\nfunction parsePoetryLock(content: string, tree: DependencyTree): void {\n // Collect names of already-known direct dependencies so we can cross-ref\n const directNames = new Set<string>();\n for (const node of tree.nodes.values()) {\n if (node.isDirect) {\n directNames.add(node.name);\n }\n }\n\n // Split on [[package]] headers. The first element is everything before the\n // first header (metadata / preamble) which we skip.\n const blocks = content.split(/^\\[\\[package\\]\\]\\s*$/m);\n\n for (const block of blocks) {\n const nameMatch = block.match(/^\\s*name\\s*=\\s*\"([^\"]+)\"/m);\n const versionMatch = block.match(/^\\s*version\\s*=\\s*\"([^\"]+)\"/m);\n\n if (!nameMatch) continue;\n\n const name = normalizePyPIName(nameMatch[1]);\n const version = versionMatch ? versionMatch[1] : \"*\";\n\n const isDirect = directNames.has(name);\n const key = `${name}@${version}`;\n\n if (tree.nodes.has(key)) continue;\n\n tree.nodes.set(\n key,\n createDependencyNode({\n name,\n version,\n registry: \"pypi\",\n depth: isDirect ? 0 : 1,\n isDirect,\n parent: null,\n }),\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// PythonParser\n// ---------------------------------------------------------------------------\n\nexport class PythonParser extends BaseParser {\n readonly name = \"python\";\n\n async detect(dir: string): Promise<boolean> {\n const checks = await Promise.all([\n fileExists(join(dir, \"requirements.txt\")),\n fileExists(join(dir, \"pyproject.toml\")),\n fileExists(join(dir, \"Pipfile\")),\n fileExists(join(dir, \"poetry.lock\")),\n ]);\n return checks.some(Boolean);\n }\n\n async parse(dir: string): Promise<DependencyTree> {\n const reqPath = join(dir, \"requirements.txt\");\n const pyprojectPath = join(dir, \"pyproject.toml\");\n const pipfileLockPath = join(dir, \"Pipfile.lock\");\n const poetryLockPath = join(dir, \"poetry.lock\");\n\n // Determine manifest path for the tree metadata\n let manifestPath = dir;\n if (await fileExists(pyprojectPath)) {\n manifestPath = pyprojectPath;\n } else if (await fileExists(reqPath)) {\n manifestPath = reqPath;\n }\n\n const tree = createDependencyTree(\"python-project\", manifestPath);\n\n // Parse requirements.txt if it exists\n if (await fileExists(reqPath)) {\n const content = await readText(reqPath);\n parseRequirementsTxt(content, tree);\n }\n\n // Parse pyproject.toml if it exists (may add more deps)\n if (await fileExists(pyprojectPath)) {\n const content = await readText(pyprojectPath);\n addPyprojectDeps(content, tree);\n\n // Try to extract project name from pyproject.toml\n const nameMatch = content.match(/^\\s*name\\s*=\\s*\"([^\"]+)\"/m);\n if (nameMatch) {\n tree.root = normalizePyPIName(nameMatch[1]);\n }\n }\n\n // If Pipfile.lock exists, parse transitive dependencies from it\n if (await fileExists(pipfileLockPath)) {\n const lockData = await readJson<PipfileLockJson>(pipfileLockPath);\n parsePipfileLock(lockData, tree);\n }\n\n // If poetry.lock exists, parse locked dependencies from it\n if (await fileExists(poetryLockPath)) {\n const content = await readText(poetryLockPath);\n parsePoetryLock(content, tree);\n }\n\n // Recount totals\n tree.totalDirect = 0;\n tree.totalTransitive = 0;\n for (const node of tree.nodes.values()) {\n if (node.isDirect) {\n tree.totalDirect++;\n } else {\n tree.totalTransitive++;\n }\n }\n\n return tree;\n }\n}\n","/**\n * JSON file-based cache with TTL support.\n *\n * Stores data at `~/.dep-oracle/cache.json`. Zero native dependencies —\n * works with `npx` on every OS without build tools.\n */\n\nimport { readFileSync, writeFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_TTL_SECONDS = 86_400; // 24 hours\nconst CACHE_DIR = join(homedir(), \".dep-oracle\");\nconst CACHE_PATH = join(CACHE_DIR, \"cache.json\");\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\ninterface CacheEntry {\n value: unknown;\n createdAt: number; // epoch seconds\n ttl: number; // seconds\n}\n\ntype CacheStore = Record<string, CacheEntry>;\n\n// ---------------------------------------------------------------------------\n// CacheManager\n// ---------------------------------------------------------------------------\n\nexport class CacheManager {\n private store: CacheStore;\n private readonly filePath: string;\n\n constructor(filePath: string = CACHE_PATH) {\n this.filePath = filePath;\n\n // Ensure directory exists\n const dir = filePath === CACHE_PATH ? CACHE_DIR : join(filePath, \"..\");\n mkdirSync(dir, { recursive: true });\n\n // Load existing cache\n this.store = this.load();\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /**\n * Retrieve a cached value by key. Returns `null` when the key does not\n * exist or has expired.\n */\n get<T>(key: string): T | null {\n const entry = this.store[key];\n if (!entry) return null;\n\n const now = Math.floor(Date.now() / 1000);\n if (now - entry.createdAt > entry.ttl) {\n delete this.store[key];\n this.persist();\n return null;\n }\n\n return entry.value as T;\n }\n\n /**\n * Store a value in the cache.\n */\n set<T>(key: string, value: T, ttl: number = DEFAULT_TTL_SECONDS): void {\n const now = Math.floor(Date.now() / 1000);\n this.store[key] = { value, createdAt: now, ttl };\n this.persist();\n }\n\n /**\n * Check whether a non-expired entry exists for the given key.\n */\n has(key: string): boolean {\n return this.get<unknown>(key) !== null;\n }\n\n /**\n * Delete all entries from the cache.\n */\n clear(): void {\n this.store = {};\n this.persist();\n }\n\n /**\n * Remove all expired entries.\n */\n cleanup(): number {\n const now = Math.floor(Date.now() / 1000);\n let removed = 0;\n\n for (const [key, entry] of Object.entries(this.store)) {\n if (now - entry.createdAt > entry.ttl) {\n delete this.store[key];\n removed++;\n }\n }\n\n if (removed > 0) this.persist();\n return removed;\n }\n\n /**\n * Return a human-readable string describing how old the cached entry is.\n */\n getCacheAge(key: string): string | null {\n const entry = this.store[key];\n if (!entry) return null;\n\n const now = Math.floor(Date.now() / 1000);\n const ageSeconds = now - entry.createdAt;\n\n if (ageSeconds < 60) return \"just now\";\n\n const ageMinutes = Math.floor(ageSeconds / 60);\n if (ageMinutes < 60) {\n return `${ageMinutes} minute${ageMinutes === 1 ? \"\" : \"s\"} ago`;\n }\n\n const ageHours = Math.floor(ageMinutes / 60);\n if (ageHours < 24) {\n return `${ageHours} hour${ageHours === 1 ? \"\" : \"s\"} ago`;\n }\n\n const ageDays = Math.floor(ageHours / 24);\n return `${ageDays} day${ageDays === 1 ? \"\" : \"s\"} ago`;\n }\n\n /**\n * Return the ISO-8601 timestamp of when a key was cached, or `null`.\n */\n getCachedAt(key: string): string | null {\n const entry = this.store[key];\n if (!entry) return null;\n return new Date(entry.createdAt * 1000).toISOString();\n }\n\n /**\n * Return total number of (non-expired) entries in the cache.\n */\n size(): number {\n const now = Math.floor(Date.now() / 1000);\n let count = 0;\n for (const entry of Object.values(this.store)) {\n if (now - entry.createdAt <= entry.ttl) count++;\n }\n return count;\n }\n\n /**\n * No-op for API compatibility. JSON cache does not need explicit closing.\n */\n close(): void {\n // Nothing to close — included for drop-in compatibility\n }\n\n // -----------------------------------------------------------------------\n // Persistence\n // -----------------------------------------------------------------------\n\n private load(): CacheStore {\n try {\n if (existsSync(this.filePath)) {\n const raw = readFileSync(this.filePath, \"utf-8\");\n return JSON.parse(raw) as CacheStore;\n }\n } catch (err) {\n if (err instanceof SyntaxError) {\n // Corrupted JSON — start fresh\n } else {\n // Log unexpected errors but continue with empty cache\n console.error(`Cache load error: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n return {};\n }\n\n private persist(): void {\n try {\n writeFileSync(this.filePath, JSON.stringify(this.store), \"utf-8\");\n } catch {\n // Best-effort — cache persistence should never crash the process\n }\n }\n}\n","/**\n * CollectorOrchestrator -- coordinates all collectors and runs them in parallel\n * with controlled concurrency.\n *\n * Usage:\n * const orchestrator = new CollectorOrchestrator(cacheManager, { offline: false });\n * const results = await orchestrator.collectAll('express', '4.18.2');\n */\n\nimport pLimit from 'p-limit';\n\nimport type {\n CollectorResult,\n RegistryData,\n GitHubData,\n SecurityData,\n FundingData,\n PopularityData,\n LicenseData,\n} from '../parsers/schema.js';\nimport type { CacheManager } from '../cache/store.js';\nimport { logger } from '../utils/logger.js';\n\nimport { RegistryCollector } from './registry.js';\nimport { GitHubCollector } from './github.js';\nimport { SecurityCollector } from './security.js';\nimport { FundingCollector } from './funding.js';\nimport { PopularityCollector } from './popularity.js';\nimport { LicenseCollector } from './license.js';\nimport type { BaseCollector } from './base.js';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface AllCollectorResults {\n registry: CollectorResult<RegistryData>;\n github: CollectorResult<GitHubData>;\n security: CollectorResult<SecurityData>;\n funding: CollectorResult<FundingData>;\n popularity: CollectorResult<PopularityData>;\n license: CollectorResult<LicenseData>;\n}\n\nexport interface OrchestratorOptions {\n /** When true, only cached data is returned. No network requests. */\n offline?: boolean;\n /** GitHub personal access token for higher rate limits. */\n githubToken?: string;\n /** Maximum concurrent collector tasks (default: 10). */\n concurrency?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\nexport class CollectorOrchestrator {\n private readonly cache: CacheManager;\n private readonly options: Required<OrchestratorOptions>;\n\n private readonly registryCollector: RegistryCollector;\n private readonly githubCollector: GitHubCollector;\n private readonly securityCollector: SecurityCollector;\n private readonly fundingCollector: FundingCollector;\n private readonly popularityCollector: PopularityCollector;\n private readonly licenseCollector: LicenseCollector;\n\n constructor(cache: CacheManager, options: OrchestratorOptions = {}) {\n this.cache = cache;\n this.options = {\n offline: options.offline ?? false,\n githubToken: options.githubToken ?? process.env.GITHUB_TOKEN ?? '',\n concurrency: options.concurrency ?? 10,\n };\n\n this.registryCollector = new RegistryCollector(this.cache);\n this.githubCollector = new GitHubCollector(this.cache, this.options.githubToken || undefined);\n this.securityCollector = new SecurityCollector(this.cache);\n this.fundingCollector = new FundingCollector(this.cache, this.options.githubToken || undefined);\n this.popularityCollector = new PopularityCollector(this.cache);\n this.licenseCollector = new LicenseCollector(this.cache);\n }\n\n /**\n * Run all collectors for the given package and version.\n *\n * In online mode every collector is invoked (cache-first). In offline mode\n * only the cache is consulted; if there is no cached entry the result gets\n * `status: 'offline'` with `data: null`.\n */\n async collectAll(\n packageName: string,\n version: string,\n ): Promise<AllCollectorResults> {\n logger.info(\n `Collecting data for ${packageName}@${version} (offline=${String(this.options.offline)})`,\n );\n\n const limit = pLimit(this.options.concurrency);\n\n type CollectorEntry<T> = {\n key: keyof AllCollectorResults;\n collector: BaseCollector<T>;\n };\n\n // Type-safe collector list. We use `unknown` for the heterogeneous array\n // and cast at assignment time.\n const entries: Array<CollectorEntry<unknown>> = [\n { key: 'registry', collector: this.registryCollector as BaseCollector<unknown> },\n { key: 'github', collector: this.githubCollector as BaseCollector<unknown> },\n { key: 'security', collector: this.securityCollector as BaseCollector<unknown> },\n { key: 'funding', collector: this.fundingCollector as BaseCollector<unknown> },\n { key: 'popularity', collector: this.popularityCollector as BaseCollector<unknown> },\n { key: 'license', collector: this.licenseCollector as BaseCollector<unknown> },\n ];\n\n const results = {} as AllCollectorResults;\n\n const COLLECTOR_TIMEOUT = 30_000; // 30 seconds per collector\n\n const tasks = entries.map(({ key, collector }) =>\n limit(async () => {\n let result: CollectorResult<unknown>;\n\n if (this.options.offline) {\n result = await this.offlineCollect(collector, packageName, version);\n } else {\n try {\n result = await Promise.race([\n this.onlineCollect(collector, packageName, version),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error('Collector timeout')), COLLECTOR_TIMEOUT),\n ),\n ]);\n } catch {\n logger.warn(`[${collector.name}] ${packageName}@${version} => timeout (${COLLECTOR_TIMEOUT}ms)`);\n result = {\n status: 'error',\n data: null,\n error: `Timeout after ${COLLECTOR_TIMEOUT / 1000}s`,\n collectedAt: new Date().toISOString(),\n };\n }\n }\n\n logger.info(\n `[${collector.name}] ${packageName}@${version} => ${result.status}`,\n );\n\n (results as unknown as Record<string, CollectorResult<unknown>>)[key] = result;\n }),\n );\n\n await Promise.all(tasks);\n\n return results;\n }\n\n // ---------------------------------------------------------------------------\n // Online / Offline strategies\n // ---------------------------------------------------------------------------\n\n /**\n * Normal collection: delegate to the collector which checks cache internally.\n */\n private async onlineCollect<T>(\n collector: BaseCollector<T>,\n packageName: string,\n version: string,\n ): Promise<CollectorResult<T>> {\n try {\n return await collector.collect(packageName, version);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(`Unhandled error in ${collector.name}: ${message}`);\n\n return {\n status: 'error',\n data: null,\n error: message,\n collectedAt: new Date().toISOString(),\n };\n }\n }\n\n /**\n * Offline collection: only look in the cache. If nothing is cached return\n * a result with `status: 'offline'`.\n */\n private async offlineCollect<T>(\n collector: BaseCollector<T>,\n packageName: string,\n version: string,\n ): Promise<CollectorResult<T>> {\n try {\n const key = `${collector.name}:${packageName}@${version}`;\n const cached = await this.cache.get<T>(key);\n\n if (cached !== null && cached !== undefined) {\n logger.debug(`Offline cache hit: ${key}`);\n return {\n status: 'cached',\n data: cached,\n collectedAt: new Date().toISOString(),\n };\n }\n\n return {\n status: 'offline',\n data: null,\n collectedAt: new Date().toISOString(),\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.warn(`Offline cache read failed for ${collector.name}: ${message}`);\n\n return {\n status: 'offline',\n data: null,\n collectedAt: new Date().toISOString(),\n };\n }\n }\n}\n","/**\n * Abstract base class for all data collectors.\n *\n * Every collector extends BaseCollector<T> and returns CollectorResult<T>.\n * Provides transparent caching: subclasses call getCached / setCache and the\n * base takes care of serialisation through CacheManager.\n */\n\nimport type { CollectorResult } from '../parsers/schema.js';\nimport type { CacheManager } from '../cache/store.js';\nimport { logger } from '../utils/logger.js';\n\nexport abstract class BaseCollector<T> {\n /** Human-readable collector name used in logs and cache keys. */\n abstract readonly name: string;\n\n protected readonly cache: CacheManager;\n\n /** Default cache TTL in seconds (24 hours). */\n protected readonly defaultTTL: number = 86_400;\n\n constructor(cache: CacheManager) {\n this.cache = cache;\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /** Collect data for the given package + version. */\n abstract collect(\n packageName: string,\n version: string,\n ): Promise<CollectorResult<T>>;\n\n // ---------------------------------------------------------------------------\n // Cache helpers\n // ---------------------------------------------------------------------------\n\n /** Build a deterministic cache key. */\n protected cacheKey(pkg: string, version: string): string {\n return `${this.name}:${pkg}@${version}`;\n }\n\n /**\n * Return a cached CollectorResult if one exists, otherwise `null`.\n *\n * When a cache hit is found the result is returned with `status: 'cached'`\n * so callers can differentiate between fresh and cached data.\n */\n protected async getCached(\n pkg: string,\n version: string,\n ): Promise<CollectorResult<T> | null> {\n const key = this.cacheKey(pkg, version);\n\n try {\n const cached = await this.cache.get<T>(key);\n if (cached !== null && cached !== undefined) {\n logger.debug(`Cache hit for ${key}`);\n return {\n status: 'cached',\n data: cached,\n collectedAt: new Date().toISOString(),\n };\n }\n } catch (err) {\n logger.warn(\n `Cache read failed for ${key}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n return null;\n }\n\n /**\n * Persist collector data in the cache.\n *\n * Failures are logged but never thrown -- caching is best-effort.\n */\n protected async setCache(\n pkg: string,\n version: string,\n data: T,\n ttl: number = this.defaultTTL,\n ): Promise<void> {\n const key = this.cacheKey(pkg, version);\n\n try {\n await this.cache.set<T>(key, data, ttl);\n logger.debug(`Cache set for ${key} (ttl=${ttl}s)`);\n } catch (err) {\n logger.warn(\n `Cache write failed for ${key}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n}\n","/**\n * RegistryCollector -- fetches package metadata from the npm registry.\n *\n * Data sources:\n * - https://registry.npmjs.org/{package} (metadata)\n * - https://api.npmjs.org/downloads/point/last-week/{package} (downloads)\n */\n\nimport type { CollectorResult, RegistryData } from '../parsers/schema.js';\nimport type { CacheManager } from '../cache/store.js';\nimport { logger } from '../utils/logger.js';\nimport { BaseCollector } from './base.js';\n\n/** Shape returned by the npm downloads API. */\ninterface NpmDownloadsResponse {\n downloads: number;\n start: string;\n end: string;\n package: string;\n}\n\n/** Subset of the npm registry packument we actually use. */\ninterface NpmPackument {\n name: string;\n description?: string;\n 'dist-tags'?: Record<string, string>;\n time?: Record<string, string>;\n versions?: Record<string, NpmVersionInfo>;\n repository?: { type?: string; url?: string } | string;\n license?: string;\n}\n\ninterface NpmVersionInfo {\n deprecated?: string;\n [key: string]: unknown;\n}\n\nexport class RegistryCollector extends BaseCollector<RegistryData> {\n readonly name = 'registry';\n\n constructor(cache: CacheManager) {\n super(cache);\n }\n\n async collect(\n packageName: string,\n version: string,\n ): Promise<CollectorResult<RegistryData>> {\n // Check cache first\n const cached = await this.getCached(packageName, version);\n if (cached) return cached;\n\n try {\n const [packument, downloads] = await Promise.all([\n this.fetchPackument(packageName),\n this.fetchWeeklyDownloads(packageName),\n ]);\n\n const versionCount = packument.versions\n ? Object.keys(packument.versions).length\n : 0;\n\n // Determine last publish date from the time map\n const timeEntries = packument.time ?? {};\n const publishDates = Object.entries(timeEntries)\n .filter(([key]) => key !== 'created' && key !== 'modified')\n .map(([, value]) => new Date(value).getTime())\n .sort((a, b) => b - a);\n\n const lastPublishDate = publishDates.length > 0\n ? new Date(publishDates[0]).toISOString()\n : null;\n\n // Check if the requested version is deprecated\n const versionInfo = packument.versions?.[version];\n const deprecated = versionInfo?.deprecated\n ? String(versionInfo.deprecated)\n : null;\n\n const data: RegistryData = {\n packageName,\n version,\n description: packument.description ?? null,\n lastPublishDate,\n versionCount,\n deprecated,\n weeklyDownloads: downloads,\n license: packument.license ?? null,\n repositoryUrl: this.extractRepoUrl(packument),\n };\n\n await this.setCache(packageName, version, data);\n\n return {\n status: 'success',\n data,\n collectedAt: new Date().toISOString(),\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(`RegistryCollector failed for ${packageName}@${version}: ${message}`);\n\n return {\n status: 'error',\n data: null,\n error: message,\n collectedAt: new Date().toISOString(),\n };\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n private async fetchPackument(packageName: string): Promise<NpmPackument> {\n const url = `https://registry.npmjs.org/${encodeURIComponent(packageName)}`;\n logger.debug(`Fetching packument: ${url}`);\n\n const res = await fetch(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (!res.ok) {\n throw new Error(`npm registry returned ${res.status} for ${packageName}`);\n }\n\n return (await res.json()) as NpmPackument;\n }\n\n private async fetchWeeklyDownloads(packageName: string): Promise<number> {\n const url = `https://api.npmjs.org/downloads/point/last-week/${encodeURIComponent(packageName)}`;\n logger.debug(`Fetching weekly downloads: ${url}`);\n\n try {\n const res = await fetch(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (!res.ok) {\n logger.warn(`Downloads API returned ${res.status} for ${packageName}`);\n return 0;\n }\n\n const body = (await res.json()) as NpmDownloadsResponse;\n return body.downloads ?? 0;\n } catch {\n logger.warn(`Could not fetch download stats for ${packageName}`);\n return 0;\n }\n }\n\n /**\n * Extract a normalised GitHub/repo URL from the packument.\n * npm stores repo URLs in several formats; we normalise to https.\n */\n private extractRepoUrl(packument: NpmPackument): string | null {\n const repo = packument.repository;\n if (!repo) return null;\n\n const raw = typeof repo === 'string' ? repo : repo.url;\n if (!raw) return null;\n\n // Normalise git+https://..., git://..., git+ssh://git@github.com/... etc.\n return raw\n .replace(/^git\\+/, '')\n .replace(/^git:\\/\\//, 'https://')\n .replace(/^ssh:\\/\\/git@github\\.com/, 'https://github.com')\n .replace(/^git@github\\.com:/, 'https://github.com/')\n .replace(/\\.git$/, '');\n }\n}\n","/**\n * GitHubCollector -- fetches repository health metrics from the GitHub REST API.\n *\n * Data sources:\n * - /repos/{owner}/{repo} (stars, forks, issues)\n * - /repos/{owner}/{repo}/contributors (contributor count via Link header)\n * - /repos/{owner}/{repo}/commits (recent activity, latest commit)\n * - /repos/{owner}/{repo}/contents/.github/FUNDING.yml (sponsor / funding info)\n *\n * An optional GITHUB_TOKEN env var is used to raise rate limits from 60 to\n * 5 000 requests / hour.\n */\n\nimport type { CollectorResult, GitHubData } from '../parsers/schema.js';\nimport type { CacheManager } from '../cache/store.js';\nimport { logger } from '../utils/logger.js';\nimport { BaseCollector } from './base.js';\n\ninterface GitHubRepoResponse {\n stargazers_count: number;\n forks_count: number;\n open_issues_count: number;\n updated_at: string;\n archived: boolean;\n disabled: boolean;\n default_branch: string;\n}\n\ninterface GitHubCommitItem {\n sha: string;\n commit: {\n committer: { date: string } | null;\n message: string;\n };\n}\n\nexport class GitHubCollector extends BaseCollector<GitHubData> {\n readonly name = 'github';\n\n private readonly token: string | undefined;\n\n constructor(cache: CacheManager, githubToken?: string) {\n super(cache);\n this.token = githubToken ?? process.env.GITHUB_TOKEN;\n }\n\n async collect(\n packageName: string,\n version: string,\n ): Promise<CollectorResult<GitHubData>> {\n // Check cache first\n const cached = await this.getCached(packageName, version);\n if (cached) return cached;\n\n try {\n const repoSlug = await this.resolveRepoSlug(packageName);\n\n if (!repoSlug) {\n return {\n status: 'error',\n data: null,\n error: 'No GitHub repository found',\n collectedAt: new Date().toISOString(),\n };\n }\n\n const { owner, repo } = repoSlug;\n\n // Fire all requests in parallel -- each one is independently safe.\n const [repoInfo, contributorCount, recentCommitCount, latestCommit, hasFunding] =\n await Promise.all([\n this.fetchRepoInfo(owner, repo),\n this.fetchContributorCount(owner, repo),\n this.fetchRecentCommitCount(owner, repo),\n this.fetchLatestCommit(owner, repo),\n this.checkFundingYml(owner, repo),\n ]);\n\n const data: GitHubData = {\n owner,\n repo,\n stars: repoInfo.stargazers_count,\n forks: repoInfo.forks_count,\n openIssues: repoInfo.open_issues_count,\n updatedAt: repoInfo.updated_at,\n archived: repoInfo.archived,\n defaultBranch: repoInfo.default_branch,\n contributorCount,\n recentCommitCount,\n lastCommitDate: latestCommit\n ? latestCommit.commit.committer?.date ?? null\n : null,\n lastCommitSha: latestCommit?.sha ?? null,\n hasFundingYml: hasFunding,\n };\n\n await this.setCache(packageName, version, data);\n\n return {\n status: 'success',\n data,\n collectedAt: new Date().toISOString(),\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(`GitHubCollector failed for ${packageName}@${version}: ${message}`);\n\n return {\n status: 'error',\n data: null,\n error: message,\n collectedAt: new Date().toISOString(),\n };\n }\n }\n\n // ---------------------------------------------------------------------------\n // Repo slug resolution\n // ---------------------------------------------------------------------------\n\n /**\n * Determine the GitHub owner/repo from the npm registry metadata.\n * Falls back to a well-known heuristic for scoped packages.\n */\n private async resolveRepoSlug(\n packageName: string,\n ): Promise<{ owner: string; repo: string } | null> {\n try {\n const url = `https://registry.npmjs.org/${encodeURIComponent(packageName)}`;\n const res = await fetch(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (!res.ok) return null;\n\n const body = (await res.json()) as {\n repository?: { url?: string } | string;\n };\n\n const repoField = body.repository;\n const raw = typeof repoField === 'string' ? repoField : repoField?.url;\n\n if (!raw) return null;\n\n return this.parseGitHubUrl(raw);\n } catch {\n return null;\n }\n }\n\n /** Extract owner/repo from a variety of GitHub URL formats. */\n private parseGitHubUrl(\n raw: string,\n ): { owner: string; repo: string } | null {\n const normalised = raw\n .replace(/^git\\+/, '')\n .replace(/^git:\\/\\//, 'https://')\n .replace(/^ssh:\\/\\/git@github\\.com/, 'https://github.com')\n .replace(/^git@github\\.com:/, 'https://github.com/')\n .replace(/\\.git$/, '');\n\n const match = normalised.match(\n /github\\.com\\/([^/]+)\\/([^/]+)/,\n );\n\n if (!match) return null;\n\n const owner = match[1];\n const repo = match[2];\n // Validate GitHub owner/repo format\n const GITHUB_NAME = /^[a-zA-Z0-9]([a-zA-Z0-9._-]*[a-zA-Z0-9])?$/;\n if (!GITHUB_NAME.test(owner) || !GITHUB_NAME.test(repo)) return null;\n\n return { owner, repo };\n }\n\n // ---------------------------------------------------------------------------\n // GitHub API calls\n // ---------------------------------------------------------------------------\n\n private headers(): Record<string, string> {\n const h: Record<string, string> = {\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n };\n if (this.token) {\n h.Authorization = `Bearer ${this.token}`;\n }\n return h;\n }\n\n private async fetchRepoInfo(\n owner: string,\n repo: string,\n ): Promise<GitHubRepoResponse> {\n const url = `https://api.github.com/repos/${owner}/${repo}`;\n logger.debug(`GitHub: fetching repo info ${url}`);\n\n const res = await fetch(url, { headers: this.headers() });\n if (!res.ok) {\n throw new Error(`GitHub API ${res.status} for ${url}`);\n }\n return (await res.json()) as GitHubRepoResponse;\n }\n\n /**\n * Get total contributor count using the Link header pagination trick.\n * We request per_page=1&anon=true and read the `last` page number.\n */\n private async fetchContributorCount(\n owner: string,\n repo: string,\n ): Promise<number> {\n const url = `https://api.github.com/repos/${owner}/${repo}/contributors?per_page=1&anon=true`;\n logger.debug(`GitHub: fetching contributor count ${url}`);\n\n try {\n const res = await fetch(url, { headers: this.headers() });\n if (!res.ok) return 0;\n\n const count = this.extractLastPage(res.headers.get('link'));\n // If there is no Link header the repo has a single page of contributors.\n if (count !== null) return count;\n\n // Fallback: count items in the response body.\n const body = (await res.json()) as unknown[];\n return body.length;\n } catch {\n return 0;\n }\n }\n\n /**\n * Count commits in the last 30 days via the same Link-header trick.\n */\n private async fetchRecentCommitCount(\n owner: string,\n repo: string,\n ): Promise<number> {\n const since = new Date(\n Date.now() - 30 * 24 * 60 * 60 * 1000,\n ).toISOString();\n\n const url = `https://api.github.com/repos/${owner}/${repo}/commits?since=${since}&per_page=1`;\n logger.debug(`GitHub: fetching recent commit count ${url}`);\n\n try {\n const res = await fetch(url, { headers: this.headers() });\n if (!res.ok) return 0;\n\n const count = this.extractLastPage(res.headers.get('link'));\n if (count !== null) return count;\n\n const body = (await res.json()) as unknown[];\n return body.length;\n } catch {\n return 0;\n }\n }\n\n /** Fetch the single most-recent commit. */\n private async fetchLatestCommit(\n owner: string,\n repo: string,\n ): Promise<GitHubCommitItem | null> {\n const url = `https://api.github.com/repos/${owner}/${repo}/commits?per_page=1`;\n logger.debug(`GitHub: fetching latest commit ${url}`);\n\n try {\n const res = await fetch(url, { headers: this.headers() });\n if (!res.ok) return null;\n\n const body = (await res.json()) as GitHubCommitItem[];\n return body[0] ?? null;\n } catch {\n return null;\n }\n }\n\n /**\n * Check whether the repository contains a .github/FUNDING.yml file.\n * A 200 response means the file exists.\n */\n private async checkFundingYml(\n owner: string,\n repo: string,\n ): Promise<boolean> {\n const url = `https://api.github.com/repos/${owner}/${repo}/contents/.github/FUNDING.yml`;\n logger.debug(`GitHub: checking FUNDING.yml ${url}`);\n\n try {\n const res = await fetch(url, { headers: this.headers() });\n return res.ok;\n } catch {\n return false;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Utilities\n // ---------------------------------------------------------------------------\n\n /**\n * Parse the GitHub `Link` header and return the last page number.\n *\n * Link: <...?page=42>; rel=\"last\", <...?page=2>; rel=\"next\"\n *\n * Returns `null` when there is no last page (single page of results).\n */\n private extractLastPage(linkHeader: string | null): number | null {\n if (!linkHeader) return null;\n\n const match = linkHeader.match(\n /[?&]page=(\\d+)[^>]*>;\\s*rel=\"last\"/,\n );\n\n return match ? parseInt(match[1], 10) : null;\n }\n}\n","/**\n * SecurityCollector -- queries the OSV.dev API for known vulnerabilities\n * affecting an npm package.\n *\n * Data source:\n * POST https://api.osv.dev/v1/query\n */\n\nimport type { CollectorResult, SecurityData } from '../parsers/schema.js';\nimport type { CacheManager } from '../cache/store.js';\nimport { logger } from '../utils/logger.js';\nimport { BaseCollector } from './base.js';\n\n/** Subset of the OSV vulnerability schema we use. */\ninterface OsvVulnerability {\n id: string;\n summary?: string;\n modified: string;\n published?: string;\n severity?: OsvSeverity[];\n database_specific?: {\n severity?: string;\n [key: string]: unknown;\n };\n affected?: OsvAffected[];\n}\n\ninterface OsvSeverity {\n type: string;\n score: string;\n}\n\ninterface OsvAffected {\n package?: { name?: string; ecosystem?: string };\n ranges?: OsvRange[];\n versions?: string[];\n}\n\ninterface OsvRange {\n type: string;\n events: Array<{ introduced?: string; fixed?: string }>;\n}\n\ninterface OsvQueryResponse {\n vulns?: OsvVulnerability[];\n}\n\ntype SeverityLevel = 'critical' | 'high' | 'medium' | 'low' | 'unknown';\n\nexport class SecurityCollector extends BaseCollector<SecurityData> {\n readonly name = 'security';\n\n constructor(cache: CacheManager) {\n super(cache);\n }\n\n async collect(\n packageName: string,\n version: string,\n ): Promise<CollectorResult<SecurityData>> {\n // Check cache first\n const cached = await this.getCached(packageName, version);\n if (cached) return cached;\n\n try {\n const vulns = await this.queryOsv(packageName);\n\n const totalVulnerabilities = vulns.length;\n\n // Count vulnerabilities by severity\n const severityCounts: Record<SeverityLevel, number> = {\n critical: 0,\n high: 0,\n medium: 0,\n low: 0,\n unknown: 0,\n };\n\n for (const vuln of vulns) {\n const severity = this.extractSeverity(vuln);\n severityCounts[severity]++;\n }\n\n // Find the latest vulnerability date\n const vulnDates = vulns\n .map((v) => new Date(v.published ?? v.modified).getTime())\n .filter((t) => !isNaN(t))\n .sort((a, b) => b - a);\n\n const latestVulnDate = vulnDates.length > 0\n ? new Date(vulnDates[0]).toISOString()\n : null;\n\n // Estimate average patch time in days.\n // For each vuln that has a \"fixed\" event we compute introduced -> fixed delta.\n const patchDays = this.estimateAveragePatchDays(vulns);\n\n const data: SecurityData = {\n packageName,\n version,\n totalVulnerabilities,\n severityCounts,\n latestVulnDate,\n averagePatchDays: patchDays,\n vulnerabilities: vulns.map((v) => ({\n id: v.id,\n summary: v.summary ?? null,\n severity: this.extractSeverity(v),\n published: v.published ?? v.modified,\n })),\n };\n\n await this.setCache(packageName, version, data);\n\n return {\n status: 'success',\n data,\n collectedAt: new Date().toISOString(),\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(`SecurityCollector failed for ${packageName}@${version}: ${message}`);\n\n return {\n status: 'error',\n data: null,\n error: message,\n collectedAt: new Date().toISOString(),\n };\n }\n }\n\n // ---------------------------------------------------------------------------\n // OSV API\n // ---------------------------------------------------------------------------\n\n private async queryOsv(packageName: string): Promise<OsvVulnerability[]> {\n const url = 'https://api.osv.dev/v1/query';\n logger.debug(`OSV: querying vulnerabilities for ${packageName}`);\n\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n package: {\n name: packageName,\n ecosystem: 'npm',\n },\n }),\n });\n\n if (!res.ok) {\n throw new Error(`OSV API returned ${res.status}`);\n }\n\n const body = (await res.json()) as OsvQueryResponse;\n return body.vulns ?? [];\n }\n\n // ---------------------------------------------------------------------------\n // Severity extraction\n // ---------------------------------------------------------------------------\n\n /**\n * Determine the highest severity label for a vulnerability.\n *\n * OSV may provide CVSS vectors, database-specific severity strings, or\n * nothing at all. We try multiple sources in order of preference.\n */\n private extractSeverity(vuln: OsvVulnerability): SeverityLevel {\n // 1. Try CVSS score from severity array\n if (vuln.severity && vuln.severity.length > 0) {\n for (const s of vuln.severity) {\n const level = this.cvssToLevel(s.score);\n if (level !== 'unknown') return level;\n }\n }\n\n // 2. Try database_specific.severity string\n const dbSeverity = vuln.database_specific?.severity;\n if (typeof dbSeverity === 'string') {\n const normalised = dbSeverity.toLowerCase().trim();\n if (normalised === 'critical') return 'critical';\n if (normalised === 'high') return 'high';\n if (normalised === 'moderate' || normalised === 'medium') return 'medium';\n if (normalised === 'low') return 'low';\n }\n\n return 'unknown';\n }\n\n /**\n * Map a CVSS 3.x vector string to a severity level by extracting the\n * base score. If the string looks like a plain number, use it directly.\n */\n private cvssToLevel(scoreOrVector: string): SeverityLevel {\n let numeric: number;\n\n if (scoreOrVector.startsWith('CVSS:')) {\n // Extract base score: it is not embedded literally in the vector, so\n // we fall back to a simpler heuristic based on the Attack Complexity\n // and Impact metrics. A proper CVSS calculator is out of scope here,\n // so we return 'unknown' and let database_specific take over.\n return 'unknown';\n }\n\n numeric = parseFloat(scoreOrVector);\n if (isNaN(numeric)) return 'unknown';\n\n if (numeric >= 9.0) return 'critical';\n if (numeric >= 7.0) return 'high';\n if (numeric >= 4.0) return 'medium';\n if (numeric > 0) return 'low';\n\n return 'unknown';\n }\n\n // ---------------------------------------------------------------------------\n // Patch-time estimation\n // ---------------------------------------------------------------------------\n\n /**\n * Estimate average number of days between a vulnerability being introduced\n * and being fixed. Uses the range events in the OSV affected data.\n *\n * When no usable data is available, returns `null`.\n */\n private estimateAveragePatchDays(vulns: OsvVulnerability[]): number | null {\n const daysPerVuln: number[] = [];\n\n for (const vuln of vulns) {\n if (!vuln.affected) continue;\n\n for (const affected of vuln.affected) {\n if (!affected.ranges) continue;\n\n for (const range of affected.ranges) {\n let introduced: string | undefined;\n let fixed: string | undefined;\n\n for (const event of range.events) {\n if (event.introduced) introduced = event.introduced;\n if (event.fixed) fixed = event.fixed;\n }\n\n // We can only compute a meaningful delta when we have dates\n // (ECOSYSTEM or SEMVER ranges use version strings, not dates).\n // For GIT ranges the events are commit SHAs.\n // Fall back to published -> modified as a proxy.\n if (introduced && fixed) {\n // These are typically version strings, not dates. Skip.\n continue;\n }\n }\n }\n\n // Proxy: time from published to last modified (often the fix date).\n const published = vuln.published ? new Date(vuln.published).getTime() : NaN;\n const modified = new Date(vuln.modified).getTime();\n\n if (!isNaN(published) && !isNaN(modified) && modified > published) {\n const days = (modified - published) / (1000 * 60 * 60 * 24);\n if (days > 0 && days < 3650) {\n // Sanity: ignore anything over 10 years\n daysPerVuln.push(days);\n }\n }\n }\n\n if (daysPerVuln.length === 0) return null;\n\n const total = daysPerVuln.reduce((sum, d) => sum + d, 0);\n return Math.round(total / daysPerVuln.length);\n }\n}\n","/**\n * FundingCollector -- best-effort detection of project funding channels.\n *\n * Data sources:\n * - GitHub FUNDING.yml (via GitHub API)\n * - OpenCollective public profile JSON\n * - npm registry \"funding\" field\n *\n * Many packages will have no funding info at all; the collector returns\n * sensible defaults in that case and never throws.\n */\n\nimport type { CollectorResult, FundingData } from '../parsers/schema.js';\nimport type { CacheManager } from '../cache/store.js';\nimport { logger } from '../utils/logger.js';\nimport { BaseCollector } from './base.js';\n\n/** Simplified OpenCollective profile shape. */\ninterface OpenCollectiveProfile {\n slug: string;\n name?: string;\n currency?: string;\n balance?: number;\n yearlyBudget?: number;\n backersCount?: number;\n contributorsCount?: number;\n isActive?: boolean;\n}\n\nexport class FundingCollector extends BaseCollector<FundingData> {\n readonly name = 'funding';\n\n private readonly githubToken: string | undefined;\n\n constructor(cache: CacheManager, githubToken?: string) {\n super(cache);\n this.githubToken = githubToken ?? process.env.GITHUB_TOKEN;\n }\n\n async collect(\n packageName: string,\n version: string,\n ): Promise<CollectorResult<FundingData>> {\n // Check cache first\n const cached = await this.getCached(packageName, version);\n if (cached) return cached;\n\n try {\n // Gather information from multiple sources in parallel.\n const [repoSlug, npmFunding] = await Promise.all([\n this.resolveRepoSlug(packageName),\n this.fetchNpmFunding(packageName),\n ]);\n\n // Fire secondary lookups in parallel once we know the repo slug.\n const [fundingYml, openCollective] = await Promise.all([\n repoSlug\n ? this.checkFundingYml(repoSlug.owner, repoSlug.repo)\n : Promise.resolve(null),\n this.fetchOpenCollective(packageName),\n ]);\n\n const hasSponsors = fundingYml !== null && fundingYml.length > 0;\n const hasOpenCollective = openCollective !== null && (openCollective.isActive ?? false);\n const hasNpmFunding = npmFunding !== null;\n\n // Rough funding estimate based on available signals.\n let estimatedAnnualFunding = 0;\n if (openCollective?.yearlyBudget) {\n // OpenCollective reports in cents for some currencies.\n estimatedAnnualFunding = openCollective.yearlyBudget > 1_000_000\n ? Math.round(openCollective.yearlyBudget / 100)\n : openCollective.yearlyBudget;\n }\n\n const data: FundingData = {\n packageName,\n hasSponsors,\n hasOpenCollective,\n hasNpmFunding,\n openCollectiveSlug: openCollective?.slug ?? null,\n openCollectiveBackers: openCollective?.backersCount ?? 0,\n estimatedAnnualFunding,\n fundingUrls: this.buildFundingUrls(npmFunding, fundingYml, openCollective),\n };\n\n await this.setCache(packageName, version, data);\n\n return {\n status: 'success',\n data,\n collectedAt: new Date().toISOString(),\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.warn(`FundingCollector failed for ${packageName}@${version}: ${message}`);\n\n // Return defaults -- funding is entirely optional.\n const data: FundingData = {\n packageName,\n hasSponsors: false,\n hasOpenCollective: false,\n hasNpmFunding: false,\n openCollectiveSlug: null,\n openCollectiveBackers: 0,\n estimatedAnnualFunding: 0,\n fundingUrls: [],\n };\n\n return {\n status: 'success',\n data,\n collectedAt: new Date().toISOString(),\n };\n }\n }\n\n // ---------------------------------------------------------------------------\n // npm registry funding field\n // ---------------------------------------------------------------------------\n\n private async fetchNpmFunding(\n packageName: string,\n ): Promise<string | string[] | null> {\n try {\n const url = `https://registry.npmjs.org/${encodeURIComponent(packageName)}`;\n const res = await fetch(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (!res.ok) return null;\n\n const body = (await res.json()) as {\n funding?: string | { url?: string } | Array<string | { url?: string }>;\n };\n\n if (!body.funding) return null;\n\n if (typeof body.funding === 'string') return body.funding;\n if (Array.isArray(body.funding)) {\n return body.funding.map((f) =>\n typeof f === 'string' ? f : f.url ?? '',\n ).filter(Boolean);\n }\n if (typeof body.funding === 'object' && body.funding.url) {\n return body.funding.url;\n }\n\n return null;\n } catch {\n return null;\n }\n }\n\n // ---------------------------------------------------------------------------\n // GitHub FUNDING.yml\n // ---------------------------------------------------------------------------\n\n private async checkFundingYml(\n owner: string,\n repo: string,\n ): Promise<string | null> {\n const url = `https://api.github.com/repos/${owner}/${repo}/contents/.github/FUNDING.yml`;\n logger.debug(`Funding: checking FUNDING.yml ${url}`);\n\n try {\n const headers: Record<string, string> = {\n Accept: 'application/vnd.github.raw+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n };\n if (this.githubToken) {\n headers.Authorization = `Bearer ${this.githubToken}`;\n }\n\n const res = await fetch(url, { headers });\n if (!res.ok) return null;\n\n return await res.text();\n } catch {\n return null;\n }\n }\n\n // ---------------------------------------------------------------------------\n // OpenCollective\n // ---------------------------------------------------------------------------\n\n private async fetchOpenCollective(\n packageName: string,\n ): Promise<OpenCollectiveProfile | null> {\n // OpenCollective slugs are typically the package name (without scope).\n const slug = packageName.replace(/^@[^/]+\\//, '');\n const url = `https://opencollective.com/${encodeURIComponent(slug)}.json`;\n logger.debug(`Funding: checking OpenCollective ${url}`);\n\n try {\n const res = await fetch(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (!res.ok) return null;\n\n return (await res.json()) as OpenCollectiveProfile;\n } catch {\n return null;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Repo slug resolution (shared helper)\n // ---------------------------------------------------------------------------\n\n private async resolveRepoSlug(\n packageName: string,\n ): Promise<{ owner: string; repo: string } | null> {\n try {\n const url = `https://registry.npmjs.org/${encodeURIComponent(packageName)}`;\n const res = await fetch(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (!res.ok) return null;\n\n const body = (await res.json()) as {\n repository?: { url?: string } | string;\n };\n\n const repoField = body.repository;\n const raw = typeof repoField === 'string' ? repoField : repoField?.url;\n if (!raw) return null;\n\n const normalised = raw\n .replace(/^git\\+/, '')\n .replace(/^git:\\/\\//, 'https://')\n .replace(/^ssh:\\/\\/git@github\\.com/, 'https://github.com')\n .replace(/^git@github\\.com:/, 'https://github.com/')\n .replace(/\\.git$/, '');\n\n const match = normalised.match(/github\\.com\\/([^/]+)\\/([^/]+)/);\n if (!match) return null;\n\n return { owner: match[1], repo: match[2] };\n } catch {\n return null;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Utilities\n // ---------------------------------------------------------------------------\n\n private buildFundingUrls(\n npmFunding: string | string[] | null,\n fundingYml: string | null,\n oc: OpenCollectiveProfile | null,\n ): string[] {\n const urls: string[] = [];\n\n // From npm\n if (npmFunding) {\n if (typeof npmFunding === 'string') {\n urls.push(npmFunding);\n } else {\n urls.push(...npmFunding);\n }\n }\n\n // From FUNDING.yml -- parse known keys\n if (fundingYml) {\n const ghMatch = fundingYml.match(/github:\\s*(.+)/i);\n if (ghMatch) {\n const sponsors = ghMatch[1].trim()\n .replace(/^\\[/, '').replace(/]$/, '')\n .split(',')\n .map((s) => s.trim().replace(/['\"]/g, ''))\n .filter(Boolean);\n const GITHUB_USERNAME = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,37}[a-zA-Z0-9])?$/;\n for (const sponsor of sponsors) {\n if (GITHUB_USERNAME.test(sponsor)) {\n urls.push(`https://github.com/sponsors/${sponsor}`);\n }\n }\n }\n\n const ocMatch = fundingYml.match(/open_collective:\\s*(\\S+)/i);\n if (ocMatch) {\n urls.push(`https://opencollective.com/${ocMatch[1].trim()}`);\n }\n\n const kofiMatch = fundingYml.match(/ko_fi:\\s*(\\S+)/i);\n if (kofiMatch) {\n urls.push(`https://ko-fi.com/${kofiMatch[1].trim()}`);\n }\n\n const patreonMatch = fundingYml.match(/patreon:\\s*(\\S+)/i);\n if (patreonMatch) {\n urls.push(`https://patreon.com/${patreonMatch[1].trim()}`);\n }\n }\n\n // OpenCollective\n if (oc?.slug) {\n const ocUrl = `https://opencollective.com/${oc.slug}`;\n if (!urls.includes(ocUrl)) {\n urls.push(ocUrl);\n }\n }\n\n return [...new Set(urls)];\n }\n}\n","/**\n * PopularityCollector -- measures package adoption through download counts\n * and trend analysis.\n *\n * Data sources:\n * - https://api.npmjs.org/downloads/point/last-week/{package}\n * - https://api.npmjs.org/downloads/point/last-month/{package}\n * - npm registry (dependent count, if available)\n */\n\nimport type { CollectorResult, PopularityData } from '../parsers/schema.js';\nimport type { CacheManager } from '../cache/store.js';\nimport { logger } from '../utils/logger.js';\nimport { BaseCollector } from './base.js';\n\ninterface NpmDownloadsResponse {\n downloads: number;\n start: string;\n end: string;\n package: string;\n}\n\ntype DownloadTrend = 'rising' | 'stable' | 'declining';\n\nexport class PopularityCollector extends BaseCollector<PopularityData> {\n readonly name = 'popularity';\n\n constructor(cache: CacheManager) {\n super(cache);\n }\n\n async collect(\n packageName: string,\n version: string,\n ): Promise<CollectorResult<PopularityData>> {\n // Check cache first\n const cached = await this.getCached(packageName, version);\n if (cached) return cached;\n\n try {\n const [weeklyDownloads, monthlyDownloads, dependentCount] =\n await Promise.all([\n this.fetchDownloads(packageName, 'last-week'),\n this.fetchDownloads(packageName, 'last-month'),\n this.fetchDependentCount(packageName),\n ]);\n\n // Trend calculation: compare weekly vs monthly weekly-average.\n const monthlyWeeklyAvg = monthlyDownloads / 4;\n let trend: DownloadTrend = 'stable';\n\n if (monthlyWeeklyAvg > 0) {\n const ratio = weeklyDownloads / monthlyWeeklyAvg;\n if (ratio > 1.1) {\n trend = 'rising';\n } else if (ratio < 0.9) {\n trend = 'declining';\n }\n }\n\n const data: PopularityData = {\n packageName,\n weeklyDownloads,\n monthlyDownloads,\n trend,\n dependentCount,\n };\n\n await this.setCache(packageName, version, data);\n\n return {\n status: 'success',\n data,\n collectedAt: new Date().toISOString(),\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(`PopularityCollector failed for ${packageName}@${version}: ${message}`);\n\n return {\n status: 'error',\n data: null,\n error: message,\n collectedAt: new Date().toISOString(),\n };\n }\n }\n\n // ---------------------------------------------------------------------------\n // npm downloads API\n // ---------------------------------------------------------------------------\n\n private async fetchDownloads(\n packageName: string,\n period: 'last-week' | 'last-month',\n ): Promise<number> {\n const url = `https://api.npmjs.org/downloads/point/${period}/${encodeURIComponent(packageName)}`;\n logger.debug(`Popularity: fetching ${period} downloads: ${url}`);\n\n try {\n const res = await fetch(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (!res.ok) {\n logger.warn(`Downloads API returned ${res.status} for ${packageName} (${period})`);\n return 0;\n }\n\n const body = (await res.json()) as NpmDownloadsResponse;\n return body.downloads ?? 0;\n } catch {\n logger.warn(`Could not fetch ${period} downloads for ${packageName}`);\n return 0;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Dependent count\n // ---------------------------------------------------------------------------\n\n /**\n * Attempt to get the number of packages that depend on this one.\n *\n * The npm registry search API exposes a \"dependents\" count via the\n * /-/v1/search endpoint. This is an approximation.\n */\n private async fetchDependentCount(packageName: string): Promise<number> {\n const url = `https://registry.npmjs.org/-/v1/search?text=${encodeURIComponent(packageName)}&size=1`;\n logger.debug(`Popularity: fetching dependent count: ${url}`);\n\n try {\n const res = await fetch(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (!res.ok) return 0;\n\n const body = (await res.json()) as {\n objects?: Array<{\n package: { name: string };\n searchScore?: number;\n // The npm search API does not directly expose dependent count,\n // but the registry CDN response sometimes does.\n }>;\n };\n\n // If the first result is an exact match we could use its score as a\n // proxy, but the number is not directly available. Return 0 for now\n // and rely on the registry packument approach below.\n if (body.objects && body.objects.length > 0) {\n const exactMatch = body.objects.find(\n (o) => o.package.name === packageName,\n );\n if (exactMatch) {\n // searchScore is not the dependent count, but we try a second\n // lookup from the packument \"users\" field (rarely populated).\n return await this.fetchDependentCountFromRegistry(packageName);\n }\n }\n\n return 0;\n } catch {\n return 0;\n }\n }\n\n /**\n * Secondary lookup: the npm registry exposes dependent info via the\n * abbreviated packument endpoint.\n */\n private async fetchDependentCountFromRegistry(\n packageName: string,\n ): Promise<number> {\n try {\n // The dependents count is not directly in the registry JSON.\n // We use the npm website API as a best-effort approach.\n const url = `https://www.npmjs.com/package/${encodeURIComponent(packageName)}`;\n const res = await fetch(url, {\n headers: {\n Accept: 'text/html',\n 'X-Spiferack': '1', // npm returns JSON when this header is set\n },\n });\n\n if (!res.ok) return 0;\n\n const body = (await res.json()) as {\n dependents?: { dependentsCount?: number };\n };\n\n return body.dependents?.dependentsCount ?? 0;\n } catch {\n // This endpoint is undocumented and may change -- fail silently.\n return 0;\n }\n }\n}\n","/**\n * LicenseCollector -- determines the license of an npm package, maps it to\n * an SPDX identifier, and classifies its risk level.\n *\n * Risk classification:\n * safe - permissive licenses (MIT, ISC, BSD, Apache-2.0, etc.)\n * cautious - weak-copyleft licenses (LGPL, MPL, EPL)\n * risky - strong-copyleft licenses (GPL, AGPL)\n * unknown - unrecognised or missing license\n */\n\nimport type { CollectorResult, LicenseData } from '../parsers/schema.js';\nimport type { CacheManager } from '../cache/store.js';\nimport { logger } from '../utils/logger.js';\nimport { BaseCollector } from './base.js';\n\ntype LicenseRisk = 'safe' | 'cautious' | 'risky' | 'unknown';\n\n/** Map of SPDX identifiers to their risk classification. */\nconst RISK_MAP: Record<string, LicenseRisk> = {\n // Safe -- permissive\n 'MIT': 'safe',\n 'ISC': 'safe',\n 'BSD-2-Clause': 'safe',\n 'BSD-3-Clause': 'safe',\n 'Apache-2.0': 'safe',\n 'Unlicense': 'safe',\n '0BSD': 'safe',\n 'CC0-1.0': 'safe',\n 'CC-BY-4.0': 'safe',\n 'Zlib': 'safe',\n 'BlueOak-1.0.0': 'safe',\n 'MIT-0': 'safe',\n\n // Cautious -- weak copyleft\n 'LGPL-2.1': 'cautious',\n 'LGPL-2.1-only': 'cautious',\n 'LGPL-2.1-or-later': 'cautious',\n 'LGPL-3.0': 'cautious',\n 'LGPL-3.0-only': 'cautious',\n 'LGPL-3.0-or-later': 'cautious',\n 'MPL-2.0': 'cautious',\n 'EPL-2.0': 'cautious',\n 'EPL-1.0': 'cautious',\n 'CDDL-1.0': 'cautious',\n 'CDDL-1.1': 'cautious',\n\n // Risky -- strong copyleft\n 'GPL-2.0': 'risky',\n 'GPL-2.0-only': 'risky',\n 'GPL-2.0-or-later': 'risky',\n 'GPL-3.0': 'risky',\n 'GPL-3.0-only': 'risky',\n 'GPL-3.0-or-later': 'risky',\n 'AGPL-3.0': 'risky',\n 'AGPL-3.0-only': 'risky',\n 'AGPL-3.0-or-later': 'risky',\n 'SSPL-1.0': 'risky',\n 'EUPL-1.2': 'risky',\n};\n\n/** Licenses known to be OSI-approved. */\nconst OSI_APPROVED = new Set<string>([\n 'MIT', 'ISC', 'BSD-2-Clause', 'BSD-3-Clause', 'Apache-2.0',\n '0BSD', 'Unlicense',\n 'LGPL-2.1', 'LGPL-2.1-only', 'LGPL-2.1-or-later',\n 'LGPL-3.0', 'LGPL-3.0-only', 'LGPL-3.0-or-later',\n 'MPL-2.0', 'EPL-2.0', 'EPL-1.0',\n 'GPL-2.0', 'GPL-2.0-only', 'GPL-2.0-or-later',\n 'GPL-3.0', 'GPL-3.0-only', 'GPL-3.0-or-later',\n 'AGPL-3.0', 'AGPL-3.0-only', 'AGPL-3.0-or-later',\n 'CDDL-1.0', 'Artistic-2.0', 'Zlib', 'PostgreSQL',\n 'EUPL-1.2', 'ECL-2.0',\n]);\n\n/** Common non-SPDX license strings people put in package.json. */\nconst LICENSE_ALIASES: Record<string, string> = {\n 'apache 2.0': 'Apache-2.0',\n 'apache2': 'Apache-2.0',\n 'apache-2': 'Apache-2.0',\n 'apache license 2.0': 'Apache-2.0',\n 'bsd': 'BSD-2-Clause',\n 'bsd-2': 'BSD-2-Clause',\n 'bsd-3': 'BSD-3-Clause',\n 'bsd license': 'BSD-2-Clause',\n 'gpl': 'GPL-3.0',\n 'gpl-2': 'GPL-2.0',\n 'gpl-3': 'GPL-3.0',\n 'gplv2': 'GPL-2.0',\n 'gplv3': 'GPL-3.0',\n 'lgpl': 'LGPL-3.0',\n 'lgpl-2': 'LGPL-2.1',\n 'lgpl-3': 'LGPL-3.0',\n 'agpl': 'AGPL-3.0',\n 'agpl-3': 'AGPL-3.0',\n 'mpl': 'MPL-2.0',\n 'mpl-2': 'MPL-2.0',\n 'unlicensed': 'Unlicense',\n 'public domain': 'Unlicense',\n 'wtfpl': 'WTFPL',\n 'cc0': 'CC0-1.0',\n 'cc0-1.0': 'CC0-1.0',\n 'artistic-2.0': 'Artistic-2.0',\n};\n\nexport class LicenseCollector extends BaseCollector<LicenseData> {\n readonly name = 'license';\n\n constructor(cache: CacheManager) {\n super(cache);\n }\n\n async collect(\n packageName: string,\n version: string,\n ): Promise<CollectorResult<LicenseData>> {\n // Check cache first\n const cached = await this.getCached(packageName, version);\n if (cached) return cached;\n\n try {\n const rawLicense = await this.fetchLicense(packageName, version);\n const spdx = this.toSpdx(rawLicense);\n const risk = this.classifyRisk(spdx);\n const osiApproved = spdx !== null && OSI_APPROVED.has(spdx);\n\n const data: LicenseData = {\n packageName,\n version,\n raw: rawLicense,\n spdx,\n risk,\n osiApproved,\n };\n\n await this.setCache(packageName, version, data);\n\n return {\n status: 'success',\n data,\n collectedAt: new Date().toISOString(),\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(`LicenseCollector failed for ${packageName}@${version}: ${message}`);\n\n return {\n status: 'error',\n data: null,\n error: message,\n collectedAt: new Date().toISOString(),\n };\n }\n }\n\n // ---------------------------------------------------------------------------\n // npm registry\n // ---------------------------------------------------------------------------\n\n /**\n * Fetch the license string from the npm registry.\n *\n * Tries the specific version first, then falls back to the top-level\n * packument \"license\" field.\n */\n private async fetchLicense(\n packageName: string,\n version: string,\n ): Promise<string | null> {\n const url = `https://registry.npmjs.org/${encodeURIComponent(packageName)}`;\n logger.debug(`License: fetching packument ${url}`);\n\n const res = await fetch(url, {\n headers: { Accept: 'application/json' },\n });\n\n if (!res.ok) {\n throw new Error(`npm registry returned ${res.status} for ${packageName}`);\n }\n\n const body = (await res.json()) as {\n license?: string | { type?: string };\n versions?: Record<string, { license?: string | { type?: string } }>;\n };\n\n // Try version-specific license first.\n const versionInfo = body.versions?.[version];\n if (versionInfo?.license) {\n return typeof versionInfo.license === 'string'\n ? versionInfo.license\n : versionInfo.license.type ?? null;\n }\n\n // Fallback to top-level license.\n if (body.license) {\n return typeof body.license === 'string'\n ? body.license\n : body.license.type ?? null;\n }\n\n return null;\n }\n\n // ---------------------------------------------------------------------------\n // SPDX mapping\n // ---------------------------------------------------------------------------\n\n /**\n * Normalise a raw license string to an SPDX identifier.\n *\n * Handles common aliases, SPDX expression syntax (e.g. \"(MIT OR Apache-2.0)\"),\n * and case-insensitive matching.\n */\n private toSpdx(raw: string | null): string | null {\n if (!raw) return null;\n\n const trimmed = raw.trim();\n if (!trimmed) return null;\n\n // If it is already a known SPDX id, return as-is.\n if (RISK_MAP[trimmed] !== undefined || OSI_APPROVED.has(trimmed)) {\n return trimmed;\n }\n\n // Try case-insensitive alias lookup.\n const lower = trimmed.toLowerCase();\n const alias = LICENSE_ALIASES[lower];\n if (alias) return alias;\n\n // Handle SPDX expressions like \"(MIT OR Apache-2.0)\".\n // We extract the first recognisable identifier for risk classification.\n const stripped = trimmed.replace(/[()]/g, '');\n const parts = stripped.split(/\\s+(?:OR|AND)\\s+/i);\n for (const part of parts) {\n const p = part.trim();\n if (RISK_MAP[p] !== undefined) return p;\n const pAlias = LICENSE_ALIASES[p.toLowerCase()];\n if (pAlias) return pAlias;\n }\n\n // Return the original trimmed value (may be a valid but uncommon SPDX id).\n return trimmed;\n }\n\n // ---------------------------------------------------------------------------\n // Risk classification\n // ---------------------------------------------------------------------------\n\n private classifyRisk(spdx: string | null): LicenseRisk {\n if (!spdx) return 'unknown';\n return RISK_MAP[spdx] ?? 'unknown';\n }\n}\n","import type {\n CollectorResult,\n RegistryData,\n GitHubData,\n SecurityData,\n FundingData,\n PopularityData,\n LicenseData,\n TrustMetrics,\n} from '../parsers/schema.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Result returned by the AllCollectorResults interface (from orchestrator). */\nexport interface AllCollectorResults {\n registry: CollectorResult<RegistryData>;\n github: CollectorResult<GitHubData>;\n security: CollectorResult<SecurityData>;\n funding: CollectorResult<FundingData>;\n popularity: CollectorResult<PopularityData>;\n license: CollectorResult<LicenseData>;\n}\n\n/** Extended trust result that includes the weighted score and metadata. */\nexport interface TrustScoreResult {\n trustScore: number;\n metrics: TrustMetrics;\n insufficientData: boolean;\n unavailableMetrics: string[];\n}\n\n/** Internal representation of a single metric evaluation. */\ninterface MetricEntry {\n key: keyof TrustMetrics;\n weight: number;\n score: number;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst NA_SCORE = -1;\n\nconst DEFAULT_WEIGHTS: Record<keyof TrustMetrics, number> = {\n security: 0.25,\n maintainer: 0.25,\n activity: 0.20,\n popularity: 0.15,\n funding: 0.10,\n license: 0.05,\n};\n\n// ---------------------------------------------------------------------------\n// TrustScoreEngine\n// ---------------------------------------------------------------------------\n\nexport class TrustScoreEngine {\n private readonly weights: Record<keyof TrustMetrics, number>;\n\n constructor(weights?: Partial<Record<keyof TrustMetrics, number>>) {\n this.weights = { ...DEFAULT_WEIGHTS, ...weights };\n const total = Object.values(this.weights).reduce((a, b) => a + b, 0);\n if (Math.abs(total - 1.0) > 0.01) {\n throw new Error(`Trust score weights must sum to 1.0, got ${total.toFixed(4)}`);\n }\n }\n\n /**\n * Calculate a full trust score from all collector results.\n * Returns the weighted score (0-100), the per-dimension metrics,\n * and metadata about data availability.\n */\n calculate(results: AllCollectorResults): TrustScoreResult {\n const securityRaw = this.calculateSecurityScore(results.security.data);\n const maintainerRaw = this.calculateMaintainerScore(results.github.data);\n const activityRaw = this.calculateActivityScore(results.registry.data, results.github.data);\n const popularityRaw = this.calculatePopularityScore(results.popularity.data);\n const fundingRaw = this.calculateFundingScore(results.funding.data);\n const licenseRaw = this.calculateLicenseScore(results.license.data);\n\n const entries: MetricEntry[] = [\n { key: 'security', weight: this.weights.security, score: securityRaw },\n { key: 'maintainer', weight: this.weights.maintainer, score: maintainerRaw },\n { key: 'activity', weight: this.weights.activity, score: activityRaw },\n { key: 'popularity', weight: this.weights.popularity, score: popularityRaw },\n { key: 'funding', weight: this.weights.funding, score: fundingRaw },\n { key: 'license', weight: this.weights.license, score: licenseRaw },\n ];\n\n const unavailableMetrics = entries\n .filter((e) => e.score === NA_SCORE)\n .map((e) => e.key);\n\n const trustScore = this.computeWeightedScore(entries, unavailableMetrics);\n\n // Clamp individual metrics for the output (N/A becomes 0 in the final metrics object)\n const metrics: TrustMetrics = {\n security: clamp(securityRaw === NA_SCORE ? 0 : securityRaw),\n maintainer: clamp(maintainerRaw === NA_SCORE ? 0 : maintainerRaw),\n activity: clamp(activityRaw === NA_SCORE ? 0 : activityRaw),\n popularity: clamp(popularityRaw === NA_SCORE ? 0 : popularityRaw),\n funding: clamp(fundingRaw === NA_SCORE ? 0 : fundingRaw),\n license: clamp(licenseRaw === NA_SCORE ? 0 : licenseRaw),\n };\n\n return {\n trustScore: Math.round(trustScore),\n metrics,\n insufficientData: unavailableMetrics.length >= 3,\n unavailableMetrics,\n };\n }\n\n // -------------------------------------------------------------------------\n // Individual dimension scorers\n // -------------------------------------------------------------------------\n\n calculateSecurityScore(data: SecurityData | null): number {\n if (data === null) return NA_SCORE;\n\n const vulns = data.totalVulnerabilities;\n\n // Diminishing penalty scale -- popular packages accumulate CVEs over time,\n // so a flat per-vuln penalty is unreasonably harsh.\n let score: number;\n if (vulns === 0) {\n score = 100;\n } else if (vulns === 1) {\n score = 85;\n } else if (vulns === 2) {\n score = 72;\n } else if (vulns === 3) {\n score = 60;\n } else if (vulns === 4) {\n score = 50;\n } else {\n // 5+ vulns: diminishing penalty with a floor of 20\n score = Math.max(20, 100 - vulns * 12);\n }\n\n // Patched bonus: only if vulnerabilities exist AND patch data is available.\n // averagePatchDays > 0 means at least some vulnerabilities were patched.\n if (vulns > 0 && data.averagePatchDays !== null && data.averagePatchDays > 0) {\n if (data.averagePatchDays <= 7) {\n // Fast patches: +10 bonus\n score = Math.min(100, score + 10);\n } else if (data.averagePatchDays <= 30) {\n // Patched within 30 days: +5 bonus\n score = Math.min(100, score + 5);\n }\n // Patches slower than 30 days: no bonus\n }\n\n return clamp(score);\n }\n\n calculateMaintainerScore(data: GitHubData | null): number {\n if (data === null) return NA_SCORE;\n\n let ceiling: number;\n if (data.contributorCount <= 1) {\n ceiling = 60;\n } else if (data.contributorCount <= 5) {\n ceiling = 80;\n } else {\n ceiling = 100;\n }\n\n let score = ceiling;\n\n // Commit frequency bonus/penalty (30-day window)\n if (data.recentCommitCount === 0) {\n score -= 20;\n } else if (data.recentCommitCount < 5) {\n score -= 10;\n } else if (data.recentCommitCount >= 20) {\n score = Math.min(ceiling, score + 5);\n }\n\n return clamp(score);\n }\n\n calculateActivityScore(\n registry: RegistryData | null,\n github: GitHubData | null,\n ): number {\n if (registry === null && github === null) return NA_SCORE;\n\n let publishScore = 50; // neutral default when registry data is absent\n let commitScore = 50;\n\n if (registry !== null && registry.lastPublishDate !== null) {\n const lastPublish = new Date(registry.lastPublishDate);\n const monthsSincePublish = monthsBetween(lastPublish, new Date());\n\n if (monthsSincePublish < 3) {\n publishScore = 100;\n } else if (monthsSincePublish < 6) {\n publishScore = 80;\n } else if (monthsSincePublish < 12) {\n publishScore = 50;\n } else if (monthsSincePublish < 24) {\n publishScore = 20;\n } else {\n publishScore = 0;\n }\n }\n\n if (github !== null) {\n if (github.recentCommitCount >= 30) {\n commitScore = 100;\n } else if (github.recentCommitCount >= 15) {\n commitScore = 80;\n } else if (github.recentCommitCount >= 5) {\n commitScore = 60;\n } else if (github.recentCommitCount >= 1) {\n commitScore = 40;\n } else {\n commitScore = 10;\n }\n }\n\n // When both are available, weight publish 60% and commit 40%\n if (registry !== null && github !== null) {\n return clamp(Math.round(publishScore * 0.6 + commitScore * 0.4));\n }\n\n // Only one source available — use it directly\n return clamp(registry !== null ? publishScore : commitScore);\n }\n\n calculatePopularityScore(data: PopularityData | null): number {\n if (data === null) return NA_SCORE;\n\n const dl = data.weeklyDownloads;\n\n if (dl >= 10_000_000) return 100;\n if (dl >= 1_000_000) return 90;\n if (dl >= 100_000) return 75;\n if (dl >= 10_000) return 60;\n if (dl >= 1_000) return 40;\n if (dl >= 100) return 25;\n return 10;\n }\n\n calculateFundingScore(data: FundingData | null): number {\n if (data === null) return NA_SCORE;\n\n // Determine the highest tier of funding\n if (data.estimatedAnnualFunding >= 50_000) {\n // Corporate-level funding\n return 90;\n }\n\n if (data.hasOpenCollective) return 70;\n if (data.hasSponsors) return 60;\n if (data.hasNpmFunding) return 65;\n\n // No meaningful funding\n return 30;\n }\n\n calculateLicenseScore(data: LicenseData | null): number {\n if (data === null) return NA_SCORE;\n\n switch (data.risk) {\n case 'safe':\n return 100;\n case 'cautious':\n return 60;\n case 'risky':\n return 30;\n case 'unknown':\n return 10;\n }\n }\n\n // -------------------------------------------------------------------------\n // Weighted score computation with N/A redistribution\n // -------------------------------------------------------------------------\n\n /**\n * Compute the final weighted score. Metrics that returned N/A have their\n * weight redistributed proportionally across the remaining metrics.\n */\n computeWeightedScore(\n metrics: MetricEntry[],\n unavailableMetrics: string[],\n ): number {\n const unavailableSet = new Set(unavailableMetrics);\n\n const available = metrics.filter((m) => !unavailableSet.has(m.key));\n\n if (available.length === 0) return 0;\n\n const totalAvailableWeight = available.reduce((sum, m) => sum + m.weight, 0);\n\n if (totalAvailableWeight === 0) return 0;\n\n // Redistribute: each available metric's effective weight is\n // its original weight scaled so all effective weights sum to 1.\n let score = 0;\n for (const m of available) {\n const effectiveWeight = m.weight / totalAvailableWeight;\n score += m.score * effectiveWeight;\n }\n\n return clamp(Math.round(score));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction clamp(value: number, min = 0, max = 100): number {\n return Math.max(min, Math.min(max, value));\n}\n\nfunction monthsBetween(from: Date, to: Date): number {\n const years = to.getFullYear() - from.getFullYear();\n const months = to.getMonth() - from.getMonth();\n const days = to.getDate() - from.getDate();\n return years * 12 + months + (days < 0 ? -0.5 : 0);\n}\n","import type { RegistryData, GitHubData } from '../parsers/schema.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type ZombieSeverity = 'none' | 'warning' | 'critical';\n\nexport interface ZombieResult {\n isZombie: boolean;\n severity: ZombieSeverity;\n lastActivity: Date | null;\n reason: string;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst MONTHS_12 = 12;\nconst MONTHS_24 = 24;\n\n// ---------------------------------------------------------------------------\n// ZombieDetector\n// ---------------------------------------------------------------------------\n\nexport class ZombieDetector {\n /**\n * Detect whether a package shows signs of abandonment (\"zombie\" status).\n *\n * Rules applied in priority order:\n * 1. Deprecated flag on the registry -> critical\n * 2. 0 active maintainers (contributorCount === 0) -> critical\n * 3. No commits in 24+ months -> critical\n * 4. No commits in 12+ months AND no publish in 12+ months -> warning\n */\n detect(\n registry: RegistryData | null,\n github: GitHubData | null,\n ): ZombieResult {\n const now = new Date();\n const reasons: string[] = [];\n\n // Track the most recent activity date from any source\n let lastActivity: Date | null = null;\n\n // -----------------------------------------------------------------------\n // Parse dates\n // -----------------------------------------------------------------------\n let lastPublishDate: Date | null = null;\n let monthsSincePublish: number | null = null;\n\n if (registry !== null && registry.lastPublishDate !== null) {\n lastPublishDate = new Date(registry.lastPublishDate);\n monthsSincePublish = monthsBetween(lastPublishDate, now);\n lastActivity = laterDate(lastActivity, lastPublishDate);\n }\n\n let lastCommitDate: Date | null = null;\n let monthsSinceCommit: number | null = null;\n\n if (github !== null && github.lastCommitDate !== null) {\n lastCommitDate = new Date(github.lastCommitDate);\n monthsSinceCommit = monthsBetween(lastCommitDate, now);\n lastActivity = laterDate(lastActivity, lastCommitDate);\n }\n\n // -----------------------------------------------------------------------\n // Rule 1: Deprecated\n // -----------------------------------------------------------------------\n if (registry !== null && registry.deprecated !== null) {\n reasons.push('Package is marked as deprecated');\n return {\n isZombie: true,\n severity: 'critical',\n lastActivity,\n reason: reasons.join('; '),\n };\n }\n\n // -----------------------------------------------------------------------\n // Rule 2: Zero active maintainers\n // -----------------------------------------------------------------------\n if (github !== null && github.contributorCount === 0) {\n reasons.push('0 active maintainers/contributors');\n return {\n isZombie: true,\n severity: 'critical',\n lastActivity,\n reason: reasons.join('; '),\n };\n }\n\n // -----------------------------------------------------------------------\n // Rule 3: No commits in 24+ months\n // -----------------------------------------------------------------------\n if (monthsSinceCommit !== null && monthsSinceCommit >= MONTHS_24) {\n reasons.push(\n `No commits in ${Math.round(monthsSinceCommit)} months, last commit ${formatDate(lastCommitDate!)}`,\n );\n return {\n isZombie: true,\n severity: 'critical',\n lastActivity,\n reason: reasons.join('; '),\n };\n }\n\n // -----------------------------------------------------------------------\n // Rule 4: No commits in 12+ months AND no publish in 12+ months\n // -----------------------------------------------------------------------\n const commitStale =\n monthsSinceCommit !== null && monthsSinceCommit >= MONTHS_12;\n const publishStale =\n monthsSincePublish !== null && monthsSincePublish >= MONTHS_12;\n\n if (commitStale && publishStale) {\n const parts: string[] = [];\n if (monthsSinceCommit !== null) {\n parts.push(`No commits in ${Math.round(monthsSinceCommit)} months`);\n }\n if (lastPublishDate !== null) {\n parts.push(`last publish ${formatDate(lastPublishDate)}`);\n }\n return {\n isZombie: true,\n severity: 'warning',\n lastActivity,\n reason: parts.join(', '),\n };\n }\n\n // Also flag warning when only one signal is available and it is stale\n if (commitStale && monthsSincePublish === null) {\n reasons.push(\n `No commits in ${Math.round(monthsSinceCommit!)} months (registry data unavailable)`,\n );\n return {\n isZombie: true,\n severity: 'warning',\n lastActivity,\n reason: reasons.join('; '),\n };\n }\n\n if (publishStale && monthsSinceCommit === null) {\n reasons.push(\n `No publish in ${Math.round(monthsSincePublish!)} months (GitHub data unavailable)`,\n );\n return {\n isZombie: true,\n severity: 'warning',\n lastActivity,\n reason: reasons.join('; '),\n };\n }\n\n // -----------------------------------------------------------------------\n // Not a zombie\n // -----------------------------------------------------------------------\n return {\n isZombie: false,\n severity: 'none',\n lastActivity,\n reason: 'Package is actively maintained',\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction monthsBetween(from: Date, to: Date): number {\n const years = to.getFullYear() - from.getFullYear();\n const months = to.getMonth() - from.getMonth();\n const days = to.getDate() - from.getDate();\n return years * 12 + months + (days < 0 ? -0.5 : 0);\n}\n\nfunction laterDate(a: Date | null, b: Date | null): Date | null {\n if (a === null) return b;\n if (b === null) return a;\n return a.getTime() >= b.getTime() ? a : b;\n}\n\nfunction formatDate(d: Date): string {\n return d.toISOString().slice(0, 10);\n}\n","import { readdir, readFile } from 'node:fs/promises';\nimport { join, relative, extname } from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface BlastRadiusResult {\n /** Number of source files that import the package. */\n affectedFiles: number;\n /** Relative paths of the affected files. */\n affectedFilesList: string[];\n /** Percentage of all source files affected (0-100). */\n percentage: number;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst SOURCE_EXTENSIONS = new Set(['.js', '.ts', '.jsx', '.tsx', '.mjs', '.mts', '.cjs', '.cts']);\n\nconst IGNORED_DIRS = new Set([\n 'node_modules',\n '.git',\n 'dist',\n 'build',\n 'out',\n 'coverage',\n '.next',\n '.nuxt',\n '__pycache__',\n '.turbo',\n]);\n\n// ---------------------------------------------------------------------------\n// BlastRadiusCalculator\n// ---------------------------------------------------------------------------\n\nexport class BlastRadiusCalculator {\n /**\n * Scan all source files under `projectDir` and count how many import\n * `packageName` (including sub-path imports like `packageName/sub`).\n */\n async calculate(\n packageName: string,\n projectDir: string,\n ): Promise<BlastRadiusResult> {\n const sourceFiles = await this.collectSourceFiles(projectDir);\n\n if (sourceFiles.length === 0) {\n return { affectedFiles: 0, affectedFilesList: [], percentage: 0 };\n }\n\n const importPattern = this.buildImportPattern(packageName);\n const affectedFilesList: string[] = [];\n\n // Read files in parallel (batched to avoid overwhelming the file system)\n const BATCH_SIZE = 50;\n for (let i = 0; i < sourceFiles.length; i += BATCH_SIZE) {\n const batch = sourceFiles.slice(i, i + BATCH_SIZE);\n const results = await Promise.all(\n batch.map(async (filePath) => {\n const matches = await this.fileContainsImport(filePath, importPattern);\n return { filePath, matches };\n }),\n );\n\n for (const { filePath, matches } of results) {\n if (matches) {\n affectedFilesList.push(relative(projectDir, filePath));\n }\n }\n }\n\n const percentage =\n sourceFiles.length > 0\n ? Math.round((affectedFilesList.length / sourceFiles.length) * 10000) / 100\n : 0;\n\n return {\n affectedFiles: affectedFilesList.length,\n affectedFilesList: affectedFilesList.sort(),\n percentage,\n };\n }\n\n // -------------------------------------------------------------------------\n // Internal helpers\n // -------------------------------------------------------------------------\n\n /**\n * Build a RegExp that matches all common import/require styles for a\n * given package name, including sub-path imports.\n *\n * Matches:\n * import ... from 'packageName'\n * import ... from 'packageName/sub'\n * import 'packageName'\n * require('packageName')\n * require('packageName/sub')\n * import('packageName') (dynamic import)\n */\n private buildImportPattern(packageName: string): RegExp {\n // Escape special regex chars in the package name (e.g. @scope/name)\n const escaped = packageName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n // Match the package name optionally followed by a sub-path.\n // The pattern must NOT match packages that merely start with the same\n // prefix (e.g. \"chalk\" should not match \"chalk-animation\").\n // We allow the name to be followed by: /, quote end, or nothing.\n const pkgPattern = `${escaped}(?:/[^'\"]*)?`;\n\n return new RegExp(\n [\n // ESM static: import ... from 'pkg' or import ... from \"pkg\"\n `from\\\\s+['\"]${pkgPattern}['\"]`,\n // ESM bare: import 'pkg' / import \"pkg\"\n `import\\\\s+['\"]${pkgPattern}['\"]`,\n // CJS require: require('pkg') or require(\"pkg\")\n `require\\\\s*\\\\(\\\\s*['\"]${pkgPattern}['\"]\\\\s*\\\\)`,\n // Dynamic import: import('pkg')\n `import\\\\s*\\\\(\\\\s*['\"]${pkgPattern}['\"]\\\\s*\\\\)`,\n ].join('|'),\n );\n }\n\n /**\n * Check whether a file's content matches the import pattern.\n */\n private async fileContainsImport(\n filePath: string,\n pattern: RegExp,\n ): Promise<boolean> {\n try {\n const content = await readFile(filePath, 'utf-8');\n return pattern.test(content);\n } catch {\n // File unreadable — skip silently\n return false;\n }\n }\n\n /**\n * Recursively collect all source files under `dir`, skipping\n * node_modules and other non-source directories.\n */\n private async collectSourceFiles(dir: string): Promise<string[]> {\n const files: string[] = [];\n\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n\n const promises: Promise<void>[] = [];\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.isDirectory()) {\n if (!IGNORED_DIRS.has(entry.name) && !entry.name.startsWith('.')) {\n promises.push(\n this.collectSourceFiles(fullPath).then((subFiles) => {\n files.push(...subFiles);\n }),\n );\n }\n } else if (entry.isFile() && SOURCE_EXTENSIONS.has(extname(entry.name))) {\n files.push(fullPath);\n }\n }\n\n await Promise.all(promises);\n } catch {\n // Directory unreadable — return empty\n }\n\n return files;\n }\n}\n","/**\n * Dynamic npm registry fetcher for popular packages.\n *\n * Fetches the top N most popular packages from the npm registry search API\n * and caches the results to a local JSON file. This supplements the hardcoded\n * POPULAR_PACKAGES list in the TyposquatDetector for more comprehensive\n * typosquat detection.\n *\n * Design decisions:\n * - Uses native `fetch` (Node 20+) -- zero additional dependencies.\n * - Caches to `~/.dep-oracle/popular-packages.json` with configurable TTL.\n * - Rate-limited to max 2 requests/second between pagination calls.\n * - Fails gracefully: returns an empty array on network/parse errors so\n * the caller can fall back to the hardcoded list.\n */\n\nimport { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { createLogger } from '../utils/logger.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst NPM_SEARCH_BASE =\n 'https://registry.npmjs.org/-/v1/search?text=boost-exact:false&popularity=1.0&quality=0.0&maintenance=0.0';\nconst PAGE_SIZE = 250;\nconst DEFAULT_COUNT = 5000;\nconst DEFAULT_CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days\nconst RATE_LIMIT_DELAY_MS = 500; // 2 requests per second\n\nconst CACHE_DIR = join(homedir(), '.dep-oracle');\nconst CACHE_FILE = join(CACHE_DIR, 'popular-packages.json');\n\nconst log = createLogger('registry-fetch');\n\n// ---------------------------------------------------------------------------\n// Cache schema\n// ---------------------------------------------------------------------------\n\ninterface PopularPackagesCache {\n fetchedAt: string; // ISO-8601\n packages: string[];\n}\n\n// ---------------------------------------------------------------------------\n// npm search API response shape (subset)\n// ---------------------------------------------------------------------------\n\ninterface NpmSearchResult {\n objects: Array<{\n package: {\n name: string;\n };\n }>;\n total: number;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Sleep for `ms` milliseconds. Used for rate-limiting between pages.\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Read the cache file and return its contents, or `null` if missing/corrupt.\n */\nfunction readCache(): PopularPackagesCache | null {\n try {\n if (!existsSync(CACHE_FILE)) return null;\n const raw = readFileSync(CACHE_FILE, 'utf-8');\n const parsed = JSON.parse(raw) as PopularPackagesCache;\n\n // Basic shape validation\n if (\n typeof parsed.fetchedAt !== 'string' ||\n !Array.isArray(parsed.packages)\n ) {\n return null;\n }\n\n return parsed;\n } catch {\n return null;\n }\n}\n\n/**\n * Write the cache file atomically (best-effort).\n */\nfunction writeCache(data: PopularPackagesCache): void {\n try {\n mkdirSync(CACHE_DIR, { recursive: true });\n writeFileSync(CACHE_FILE, JSON.stringify(data, null, 2), 'utf-8');\n } catch {\n log.warn('Failed to write popular-packages cache file');\n }\n}\n\n/**\n * Fetch a single page of results from the npm search API.\n */\nasync function fetchPage(from: number): Promise<NpmSearchResult> {\n const url = `${NPM_SEARCH_BASE}&size=${PAGE_SIZE}&from=${from}`;\n const response = await fetch(url, {\n headers: {\n 'Accept': 'application/json',\n },\n signal: AbortSignal.timeout(30_000),\n });\n\n if (!response.ok) {\n throw new Error(\n `npm search API returned ${response.status} ${response.statusText}`,\n );\n }\n\n return (await response.json()) as NpmSearchResult;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch top N popular packages from the npm registry and cache the results.\n * Uses npm's search API to find the most popular packages.\n *\n * This is used to supplement the hardcoded POPULAR_PACKAGES list\n * in the TyposquatDetector for more comprehensive detection.\n *\n * @param options.count Number of packages to fetch (default: 5000).\n * @param options.cacheTtlMs Cache time-to-live in milliseconds (default: 7 days).\n * @returns Array of package names sorted by popularity. Returns an empty\n * array on failure (offline, rate-limited, etc.) so the caller\n * can safely fall back to the hardcoded list.\n */\nexport async function fetchPopularPackages(options?: {\n count?: number;\n cacheTtlMs?: number;\n}): Promise<string[]> {\n const count = options?.count ?? DEFAULT_COUNT;\n const cacheTtlMs = options?.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;\n\n // 1. Check cache first\n const cached = readCache();\n if (cached) {\n const cacheAge = Date.now() - new Date(cached.fetchedAt).getTime();\n if (cacheAge < cacheTtlMs && cached.packages.length > 0) {\n log.info(\n `Using cached popular packages (${cached.packages.length} packages, ` +\n `cached ${Math.round(cacheAge / 1000 / 60 / 60)} hours ago)`,\n );\n return cached.packages;\n }\n log.info('Popular packages cache expired, fetching fresh data...');\n }\n\n // 2. Fetch from registry\n try {\n const totalPages = Math.ceil(count / PAGE_SIZE);\n const packages: string[] = [];\n const seen = new Set<string>();\n\n for (let page = 0; page < totalPages; page++) {\n const from = page * PAGE_SIZE;\n\n log.info(\n `Fetching popular packages from npm registry... (page ${page + 1}/${totalPages})`,\n );\n\n const result = await fetchPage(from);\n\n // Extract package names, deduplicating\n for (const obj of result.objects) {\n const name = obj.package.name;\n if (!seen.has(name)) {\n seen.add(name);\n packages.push(name);\n }\n }\n\n // If the API returned fewer results than the page size, we have\n // reached the end of available results\n if (result.objects.length < PAGE_SIZE) {\n log.info(\n `npm registry returned all available results (${packages.length} packages)`,\n );\n break;\n }\n\n // We have enough\n if (packages.length >= count) {\n break;\n }\n\n // Rate limit: wait between pages (skip wait after the last page)\n if (page < totalPages - 1) {\n await sleep(RATE_LIMIT_DELAY_MS);\n }\n }\n\n // Trim to the requested count\n const trimmed = packages.slice(0, count);\n\n // 3. Write to cache\n const cacheData: PopularPackagesCache = {\n fetchedAt: new Date().toISOString(),\n packages: trimmed,\n };\n writeCache(cacheData);\n\n log.info(`Fetched and cached ${trimmed.length} popular packages from npm registry`);\n return trimmed;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n log.warn(`Failed to fetch popular packages from npm registry: ${message}`);\n log.warn('Falling back to hardcoded popular packages list');\n\n // If we have a stale cache, return it as a best-effort fallback\n if (cached && cached.packages.length > 0) {\n log.info(\n `Returning stale cached data (${cached.packages.length} packages) as fallback`,\n );\n return cached.packages;\n }\n\n return [];\n }\n}\n","import { fetchPopularPackages } from './typosquat-registry.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface TyposquatResult {\n /** Whether the package name looks suspiciously similar to a popular package. */\n isRisky: boolean;\n /** List of popular packages that are suspiciously close. */\n similarPackages: string[];\n /** Minimum Levenshtein distance found (0 = exact match). */\n distance: number;\n}\n\n// ---------------------------------------------------------------------------\n// Top 1000+ popular npm packages (curated list, organized by category)\n// ---------------------------------------------------------------------------\n\nconst POPULAR_PACKAGES: readonly string[] = [\n // ---------------------------------------------------------------------------\n // Core frameworks — React ecosystem\n // ---------------------------------------------------------------------------\n 'react', 'react-dom', 'react-router', 'react-router-dom', 'react-redux',\n 'react-hook-form', 'react-query', 'react-select', 'react-table',\n 'react-dnd', 'react-dnd-html5-backend', 'react-beautiful-dnd',\n 'react-virtualized', 'react-window', 'react-spring',\n 'react-transition-group', 'react-modal', 'react-toastify',\n 'react-icons', 'react-helmet', 'react-helmet-async',\n 'react-intl', 'react-i18next', 'react-dropzone',\n 'react-datepicker', 'react-color', 'react-slider',\n 'react-markdown', 'react-syntax-highlighter', 'react-copy-to-clipboard',\n 'react-error-boundary', 'react-hot-toast', 'react-loading-skeleton',\n 'react-player', 'react-responsive', 'react-use',\n 'react-aria', 'react-paginate', 'react-infinite-scroll-component',\n 'react-lazy-load-image-component', 'react-card-flip',\n 'react-countup', 'react-fast-compare', 'react-is',\n 'create-react-app', 'react-scripts', 'react-app-rewired',\n 'react-refresh', 'react-dev-utils',\n\n // ---------------------------------------------------------------------------\n // Core frameworks — Redux ecosystem\n // ---------------------------------------------------------------------------\n 'redux', 'redux-thunk', 'redux-saga', 'redux-persist',\n 'redux-toolkit', 'redux-observable', 'redux-form',\n 'redux-actions', 'redux-logger', 'redux-devtools-extension',\n 'reselect', 'redux-immutable',\n\n // ---------------------------------------------------------------------------\n // Core frameworks — Next.js / Gatsby / Remix / Astro\n // ---------------------------------------------------------------------------\n 'next', 'nextjs', 'next-auth', 'next-seo', 'next-i18next',\n 'next-compose-plugins', 'next-images', 'next-transpile-modules',\n 'gatsby', 'gatsby-plugin-image', 'gatsby-plugin-sharp',\n 'gatsby-transformer-sharp', 'gatsby-source-filesystem',\n 'gatsby-plugin-react-helmet', 'gatsby-plugin-manifest',\n 'gatsby-plugin-offline', 'gatsby-plugin-mdx',\n 'remix', 'remix-run', '@remix-run/node', '@remix-run/react',\n '@remix-run/serve', '@remix-run/dev',\n 'astro', '@astrojs/react', '@astrojs/vue', '@astrojs/svelte',\n '@astrojs/tailwind', '@astrojs/node', '@astrojs/vercel',\n\n // ---------------------------------------------------------------------------\n // Core frameworks — Vue ecosystem\n // ---------------------------------------------------------------------------\n 'vue', 'vuex', 'vue-router', 'nuxt', 'nuxt3',\n 'pinia', 'vue-loader', 'vue-template-compiler',\n '@vue/cli-service', '@vue/compiler-sfc', '@vue/reactivity',\n 'vue-i18n', 'vue-meta', 'vuetify', 'quasar',\n 'vuepress', 'vitepress', 'vue-demi', 'unplugin-vue-components',\n\n // ---------------------------------------------------------------------------\n // Core frameworks — Angular ecosystem\n // ---------------------------------------------------------------------------\n 'angular', '@angular/core', '@angular/common', '@angular/compiler',\n '@angular/forms', '@angular/router', '@angular/platform-browser',\n '@angular/platform-browser-dynamic', '@angular/animations',\n '@angular/cdk', '@angular/material', '@angular/cli',\n '@angular/http', '@angular/platform-server',\n 'zone.js', 'rxjs',\n\n // ---------------------------------------------------------------------------\n // Core frameworks — Svelte / SolidJS / Preact / Lit / Ember / misc\n // ---------------------------------------------------------------------------\n 'svelte', '@sveltejs/kit', '@sveltejs/adapter-auto',\n '@sveltejs/adapter-node', '@sveltejs/adapter-static', '@sveltejs/vite-plugin-svelte',\n 'solid-js', '@solidjs/router', '@solidjs/meta',\n 'preact', 'preact-render-to-string', 'preact-router',\n 'lit', 'lit-html', 'lit-element',\n 'ember-cli', 'ember-source', '@ember/test-helpers',\n 'stencil', '@stencil/core',\n 'alpine', 'alpinejs', 'htmx.org', 'stimulus', '@hotwired/turbo',\n 'qwik', '@builder.io/qwik', '@builder.io/qwik-city',\n\n // ---------------------------------------------------------------------------\n // Build tools / bundlers\n // ---------------------------------------------------------------------------\n 'webpack', 'webpack-cli', 'webpack-dev-server', 'webpack-merge',\n 'webpack-bundle-analyzer', 'webpack-dev-middleware', 'webpack-hot-middleware',\n 'html-webpack-plugin', 'mini-css-extract-plugin', 'copy-webpack-plugin',\n 'terser-webpack-plugin', 'css-minimizer-webpack-plugin',\n 'rollup', '@rollup/plugin-node-resolve', '@rollup/plugin-commonjs',\n '@rollup/plugin-typescript', '@rollup/plugin-json', '@rollup/plugin-babel',\n '@rollup/plugin-terser', '@rollup/plugin-alias', '@rollup/plugin-replace',\n 'esbuild', 'esbuild-register', 'esbuild-loader',\n 'parcel', '@parcel/transformer-sass', '@parcel/packager-ts',\n 'vite', 'vitest', '@vitejs/plugin-react', '@vitejs/plugin-vue',\n 'turbo', 'turbopack', 'turborepo',\n 'tsup', 'unbuild', 'microbundle',\n 'swc', '@swc/core', '@swc/cli', '@swc/helpers',\n 'babel-core', '@babel/core', '@babel/preset-env', '@babel/preset-react',\n '@babel/preset-typescript', '@babel/plugin-transform-runtime',\n '@babel/runtime', '@babel/parser', '@babel/traverse',\n '@babel/generator', '@babel/types', '@babel/template',\n '@babel/plugin-proposal-decorators', '@babel/plugin-proposal-class-properties',\n 'babel-loader', 'babel-plugin-module-resolver',\n 'babel-plugin-styled-components', 'babel-jest',\n 'metro', 'metro-react-native-babel-preset',\n\n // ---------------------------------------------------------------------------\n // TypeScript ecosystem\n // ---------------------------------------------------------------------------\n 'typescript', 'ts-node', 'tsx', 'ts-jest', 'ts-loader',\n 'ts-morph', 'ts-prune', 'ts-patch', 'ts-toolbelt',\n 'tslib', 'tsconfig-paths', 'tsc-watch', 'tsutils',\n 'typedoc', 'type-fest', 'utility-types', 'ts-essentials',\n 'ttypescript', 'dts-bundle-generator', 'api-extractor',\n\n // ---------------------------------------------------------------------------\n // Testing frameworks & utilities\n // ---------------------------------------------------------------------------\n 'jest', 'jest-cli', 'jest-environment-jsdom', 'jest-circus',\n 'jest-extended', 'jest-mock-extended', 'jest-when',\n 'jest-image-snapshot',\n 'mocha', 'chai', 'chai-as-promised', 'chai-http', 'chai-spies',\n 'jasmine', 'jasmine-core', 'karma', 'karma-chrome-launcher',\n 'karma-jasmine', 'karma-webpack',\n 'vitest', '@vitest/coverage-v8', '@vitest/ui',\n 'cypress', 'cypress-real-events', 'cypress-axe',\n 'playwright', '@playwright/test', 'playwright-core',\n 'puppeteer', 'puppeteer-core', 'puppeteer-extra',\n 'sinon', 'sinon-chai', 'nock', 'msw',\n 'supertest', 'ava', 'tape', 'tap',\n 'nyc', 'c8', 'istanbul', 'istanbul-lib-coverage',\n '@testing-library/react', '@testing-library/jest-dom',\n '@testing-library/user-event', '@testing-library/vue',\n '@testing-library/angular', '@testing-library/svelte',\n '@testing-library/dom', '@testing-library/react-hooks',\n 'enzyme', 'enzyme-adapter-react-16', 'react-test-renderer',\n 'storybook', '@storybook/react', '@storybook/vue3',\n '@storybook/addon-actions', '@storybook/addon-essentials',\n '@storybook/addon-links', '@storybook/testing-library',\n 'faker', '@faker-js/faker', 'chance', 'casual',\n 'expect', 'should', 'power-assert', 'assert',\n 'testcafe', 'nightwatch', 'webdriverio', 'selenium-webdriver',\n 'detox', 'appium',\n\n // ---------------------------------------------------------------------------\n // Linting & formatting\n // ---------------------------------------------------------------------------\n 'eslint', 'prettier', 'stylelint', 'tslint',\n 'eslint-config-airbnb', 'eslint-config-airbnb-base',\n 'eslint-config-standard', 'eslint-config-prettier',\n 'eslint-config-next', 'eslint-config-react-app',\n 'eslint-plugin-react', 'eslint-plugin-react-hooks',\n 'eslint-plugin-jsx-a11y', 'eslint-plugin-import',\n 'eslint-plugin-prettier', 'eslint-plugin-jest',\n 'eslint-plugin-testing-library', 'eslint-plugin-vue',\n 'eslint-plugin-node', 'eslint-plugin-security',\n 'eslint-plugin-unicorn', 'eslint-plugin-sonarjs',\n 'eslint-plugin-simple-import-sort', 'eslint-plugin-unused-imports',\n '@typescript-eslint/parser', '@typescript-eslint/eslint-plugin',\n 'eslint-import-resolver-typescript', 'eslint-plugin-cypress',\n 'stylelint-config-standard', 'stylelint-order',\n 'husky', 'lint-staged', 'commitlint',\n '@commitlint/cli', '@commitlint/config-conventional',\n 'editorconfig', 'sort-package-json',\n 'oxlint', 'biome', '@biomejs/biome',\n\n // ---------------------------------------------------------------------------\n // HTTP clients & servers\n // ---------------------------------------------------------------------------\n 'express', 'express-session', 'express-validator',\n 'express-async-errors', 'express-async-handler',\n 'fastify', '@fastify/cors', '@fastify/helmet', '@fastify/jwt',\n '@fastify/rate-limit', '@fastify/multipart', '@fastify/static',\n '@fastify/swagger', '@fastify/cookie', '@fastify/session',\n 'koa', 'koa-router', 'koa-bodyparser', 'koa-cors', 'koa-static',\n 'hapi', '@hapi/hapi', '@hapi/joi', '@hapi/boom', '@hapi/inert',\n 'restify', 'polka', 'micro', 'sirv',\n 'axios', 'got', 'node-fetch', 'undici', 'request',\n 'superagent', 'isomorphic-fetch', 'cross-fetch',\n 'ky', 'wretch', 'redaxios', 'ofetch',\n 'http-proxy', 'http-proxy-middleware', 'express-http-proxy',\n 'connect', 'serve-handler', 'sirv-cli', 'http-server',\n 'json-server', 'miragejs', 'mockoon',\n 'needle', 'phin', 'bent', 'centra',\n\n // ---------------------------------------------------------------------------\n // Utility libraries\n // ---------------------------------------------------------------------------\n 'lodash', 'lodash-es', 'lodash.get', 'lodash.set', 'lodash.merge',\n 'lodash.clonedeep', 'lodash.debounce', 'lodash.throttle',\n 'lodash.isempty', 'lodash.isequal', 'lodash.pick', 'lodash.omit',\n 'lodash.uniq', 'lodash.flatten', 'lodash.camelcase',\n 'underscore', 'ramda', 'immer', 'immutable',\n 'uuid', 'nanoid', 'shortid', 'cuid', 'ulid',\n 'deepmerge', 'deep-equal', 'fast-deep-equal', 'object-assign',\n 'just-debounce-it', 'just-throttle', 'just-clone',\n 'change-case', 'camelcase', 'snake-case', 'param-case',\n 'pluralize', 'humanize-string', 'titleize', 'decamelize',\n 'type-is', 'is-plain-object', 'is-number', 'is-string',\n 'escape-string-regexp', 'escape-html', 'he', 'entities',\n 'defu', 'destr', 'klona', 'rfdc',\n 'invariant', 'tiny-invariant', 'warning',\n\n // ---------------------------------------------------------------------------\n // CLI tools & frameworks\n // ---------------------------------------------------------------------------\n 'chalk', 'colors', 'picocolors', 'colorette', 'ansi-colors',\n 'commander', 'yargs', 'meow', 'inquirer', 'prompts',\n 'cac', 'citty', 'cleye', 'caporal',\n 'ora', 'listr', 'listr2', 'progress', 'cli-progress',\n 'figlet', 'boxen', 'cli-table3', 'table',\n 'terminal-link', 'open', 'opn',\n 'update-notifier', 'pkg-up', 'read-pkg', 'read-pkg-up',\n 'find-up', 'locate-path', 'resolve-from', 'import-from',\n 'execa', 'shelljs', 'cross-spawn', 'cross-env',\n 'which', 'shx', 'npm-run-all', 'concurrently',\n 'cfonts', 'gradient-string', 'log-symbols', 'cli-spinners',\n 'wrap-ansi', 'slice-ansi', 'cliui', 'y18n',\n 'arg', 'mri', 'minimist', 'nopt',\n\n // ---------------------------------------------------------------------------\n // Logging libraries\n // ---------------------------------------------------------------------------\n 'winston', 'winston-daily-rotate-file', 'winston-transport',\n 'pino', 'pino-pretty', 'pino-http',\n 'bunyan', 'morgan', 'debug',\n 'log4js', 'loglevel', 'signale',\n 'consola', 'npmlog', 'fancy-log', 'roarr',\n 'tslog', 'tracer', 'electron-log',\n\n // ---------------------------------------------------------------------------\n // Database / ORM\n // ---------------------------------------------------------------------------\n 'mongoose', 'mongoose-paginate-v2', 'mongoose-lean-virtuals',\n 'sequelize', 'sequelize-cli', 'sequelize-typescript',\n 'typeorm', 'typeorm-naming-strategies',\n 'prisma', '@prisma/client', 'prisma-client-js',\n 'knex', 'objection', 'bookshelf',\n 'drizzle-orm', 'drizzle-kit',\n 'mikro-orm', '@mikro-orm/core', '@mikro-orm/postgresql',\n 'pg', 'pg-pool', 'pg-promise', 'pg-cursor',\n 'mysql', 'mysql2', 'mariadb',\n 'sqlite3', 'better-sqlite3', 'sql.js',\n 'redis', 'ioredis', 'redis-om',\n 'mongodb', 'mongodb-memory-server',\n 'cassandra-driver', 'couchbase', 'nano', 'pouchdb',\n 'nedb', 'lowdb', 'level', 'levelup', 'leveldown',\n 'dexie', 'idb', 'localforage',\n 'elasticsearch', '@elastic/elasticsearch',\n 'mssql', 'tedious', 'oracledb',\n 'kysely', 'slonik', 'massive',\n 'typegoose', '@typegoose/typegoose',\n 'waterline', 'sails',\n\n // ---------------------------------------------------------------------------\n // Validation\n // ---------------------------------------------------------------------------\n 'zod', 'joi', 'yup', 'ajv', 'class-validator',\n 'superstruct', 'io-ts', 'runtypes', 'ow',\n 'validator', 'express-validator',\n 'fastest-validator', 'fluent-json-schema',\n 'valibot', 'typebox', '@sinclair/typebox',\n 'class-transformer', 'json-schema', 'tv4',\n 'is-my-json-valid', 'schema-utils',\n\n // ---------------------------------------------------------------------------\n // Security / auth\n // ---------------------------------------------------------------------------\n 'jsonwebtoken', 'bcrypt', 'bcryptjs', 'passport',\n 'helmet', 'cors', 'csurf', 'express-rate-limit',\n 'jose', 'oauth', 'passport-jwt', 'passport-local',\n 'passport-google-oauth20', 'passport-facebook', 'passport-github2',\n 'express-jwt', 'jwks-rsa', 'node-jose',\n 'csrf-csrf', 'hpp', 'xss-clean', 'express-mongo-sanitize',\n 'rate-limiter-flexible', 'bottleneck',\n 'speakeasy', 'otplib', 'node-2fa',\n 'crypto-random-string', 'secure-random-password',\n 'grant', 'oidc-provider', 'openid-client',\n '@auth/core', 'next-auth', 'lucia', 'arctic',\n 'keycloak-js', 'auth0', '@auth0/auth0-react',\n 'supertokens-node', 'clerk', '@clerk/nextjs',\n 'iron-session', 'cookie-session', 'express-session',\n\n // ---------------------------------------------------------------------------\n // File / stream utilities\n // ---------------------------------------------------------------------------\n 'fs-extra', 'graceful-fs', 'memfs', 'vinyl-fs',\n 'glob', 'globby', 'fast-glob', 'picomatch', 'micromatch',\n 'minimatch', 'multimatch', 'anymatch',\n 'chokidar', 'watchpack', 'nsfw', 'fb-watchman',\n 'rimraf', 'mkdirp', 'make-dir', 'del', 'trash',\n 'copy', 'cpy', 'ncp', 'cpx',\n 'archiver', 'tar', 'tar-fs', 'decompress', 'extract-zip',\n 'adm-zip', 'jszip', 'yazl', 'yauzl',\n 'multer', 'formidable', 'busboy', 'multiparty',\n 'through2', 'highland', 'pump', 'pumpify',\n 'concat-stream', 'get-stream', 'into-stream',\n 'readable-stream', 'stream-buffers', 'bl',\n 'vinyl', 'vinyl-source-stream', 'vinyl-buffer',\n 'tmp', 'temp-dir', 'tempy', 'temp-write',\n 'proper-lockfile', 'lockfile', 'write-file-atomic',\n 'papaparse', 'csv-parse', 'csv-parser', 'fast-csv',\n 'xlsx', 'exceljs', 'sheetjs',\n\n // ---------------------------------------------------------------------------\n // Template engines\n // ---------------------------------------------------------------------------\n 'ejs', 'pug', 'handlebars', 'mustache', 'nunjucks',\n 'hbs', 'eta', 'liquid', 'liquidjs', 'dot', 'art-template',\n 'consolidate', 'marko', 'edge.js',\n\n // ---------------------------------------------------------------------------\n // Markdown / HTML parsing\n // ---------------------------------------------------------------------------\n 'marked', 'markdown-it', 'remark', 'remark-html', 'remark-gfm',\n 'rehype', 'rehype-stringify', 'rehype-raw',\n 'unified', 'unist-util-visit',\n 'gray-matter', 'front-matter',\n 'cheerio', 'jsdom', 'htmlparser2', 'parse5',\n 'dompurify', 'isomorphic-dompurify', 'sanitize-html', 'xss',\n 'turndown', 'showdown', 'snarkdown',\n 'mdx', '@mdx-js/react', '@mdx-js/loader',\n 'mdast-util-from-markdown', 'micromark',\n 'highlight.js', 'prismjs', 'shiki',\n\n // ---------------------------------------------------------------------------\n // Config / env\n // ---------------------------------------------------------------------------\n 'dotenv', 'dotenv-expand', 'dotenv-flow', 'dotenv-safe',\n 'config', 'convict', 'nconf', 'rc',\n 'cosmiconfig', 'lilconfig',\n 'cross-env', 'env-cmd', 'envalid', 'znv',\n 'c12', 'unconfig', 'jiti',\n\n // ---------------------------------------------------------------------------\n // Process / task management\n // ---------------------------------------------------------------------------\n 'concurrently', 'npm-run-all', 'npm-run-all2',\n 'execa', 'shelljs', 'cross-spawn', 'child-process-promise',\n 'pm2', 'nodemon', 'ts-node-dev', 'node-dev',\n 'forever', 'supervisor',\n 'workerpool', 'piscina', 'tinypool',\n 'throng', 'sticky-cluster',\n 'signal-exit', 'exit-hook', 'async-exit-hook',\n 'tasuku',\n\n // ---------------------------------------------------------------------------\n // Crypto / encoding\n // ---------------------------------------------------------------------------\n 'crypto-js', 'argon2', 'base64-js', 'buffer',\n 'tweetnacl', 'libsodium-wrappers', 'sodium-native',\n 'hash.js', 'sha.js', 'md5', 'sha1', 'sha256',\n 'scrypt-js', 'pbkdf2',\n 'base64url', 'base-x', 'bs58', 'bech32',\n 'uint8arrays', 'multihashes', 'multibase',\n 'elliptic', 'secp256k1', 'noble-secp256k1',\n 'node-forge', 'openpgp', 'sshpk',\n 'jsencrypt', 'node-rsa',\n\n // ---------------------------------------------------------------------------\n // WebSocket\n // ---------------------------------------------------------------------------\n 'ws', 'socket.io', 'socket.io-client',\n 'sockjs', 'sockjs-client', 'faye-websocket',\n 'primus', 'engine.io', 'engine.io-client',\n 'uWebSockets.js', 'websocket', 'isomorphic-ws',\n 'reconnecting-websocket', '@trpc/server', '@trpc/client',\n '@trpc/react-query', '@trpc/next',\n\n // ---------------------------------------------------------------------------\n // GraphQL\n // ---------------------------------------------------------------------------\n 'graphql', 'graphql-tag', 'graphql-tools',\n 'apollo-server', 'apollo-server-express', 'apollo-server-core',\n '@apollo/client', '@apollo/server', '@apollo/gateway',\n '@apollo/federation', '@apollo/subgraph',\n 'graphql-yoga', 'mercurius', 'type-graphql',\n 'nexus', 'pothos', '@pothos/core',\n 'graphql-request', 'graphql-ws', 'graphql-subscriptions',\n 'graphql-scalars', 'graphql-upload', 'graphql-relay',\n 'graphql-shield', 'graphql-middleware', 'graphql-depth-limit',\n 'urql', '@urql/core', '@urql/exchange-graphcache',\n 'dataloader', 'graphql-codegen',\n '@graphql-codegen/cli', '@graphql-codegen/typescript',\n 'genql', 'gql-tag-operations-preset',\n\n // ---------------------------------------------------------------------------\n // CSS-in-JS / styling\n // ---------------------------------------------------------------------------\n 'styled-components', 'emotion', '@emotion/react', '@emotion/styled',\n '@emotion/css', '@emotion/server', '@emotion/cache',\n 'tailwindcss', '@tailwindcss/forms', '@tailwindcss/typography',\n '@tailwindcss/aspect-ratio', '@tailwindcss/container-queries',\n 'postcss', 'postcss-preset-env', 'postcss-import', 'postcss-nested',\n 'postcss-modules', 'postcss-loader',\n 'autoprefixer', 'cssnano', 'postcss-flexbugs-fixes',\n 'sass', 'node-sass', 'sass-loader', 'less', 'less-loader',\n 'css-loader', 'style-loader', 'css-modules-typescript-loader',\n 'styled-jsx', 'linaria', '@linaria/core', 'vanilla-extract',\n '@vanilla-extract/css', '@vanilla-extract/recipes',\n 'stitches', '@stitches/react',\n 'classnames', 'clsx', 'cva', 'class-variance-authority',\n 'tailwind-merge', 'tailwind-variants',\n 'stylis', 'polished', 'color', 'tinycolor2',\n 'normalize.css', 'modern-normalize', 'sanitize.css',\n 'windicss', 'unocss',\n\n // ---------------------------------------------------------------------------\n // State management\n // ---------------------------------------------------------------------------\n 'mobx', 'mobx-react', 'mobx-react-lite', 'mobx-state-tree',\n 'zustand', 'jotai', 'recoil', 'valtio', 'xstate',\n 'effector', 'effector-react', 'nanostores',\n '@preact/signals', '@preact/signals-react',\n 'ngrx', '@ngrx/store', '@ngrx/effects',\n 'akita', '@datorama/akita',\n 'legend-state', 'pullstate',\n\n // ---------------------------------------------------------------------------\n // Animation / UI component libraries\n // ---------------------------------------------------------------------------\n 'framer-motion', 'react-spring', 'react-motion',\n 'gsap', 'animejs', 'anime', 'popmotion', 'motion',\n 'lottie-web', 'lottie-react', 'react-lottie',\n 'velocity-animate', 'animate.css',\n '@headlessui/react', '@headlessui/vue',\n '@radix-ui/react-dialog', '@radix-ui/react-dropdown-menu',\n '@radix-ui/react-popover', '@radix-ui/react-tooltip',\n '@radix-ui/react-select', '@radix-ui/react-tabs',\n '@radix-ui/react-accordion', '@radix-ui/react-checkbox',\n '@radix-ui/react-slider', '@radix-ui/react-switch',\n '@radix-ui/react-avatar', '@radix-ui/react-scroll-area',\n 'antd', 'ant-design-vue',\n '@ant-design/icons', '@ant-design/pro-components',\n 'bootstrap', 'react-bootstrap',\n '@chakra-ui/react', '@chakra-ui/icons',\n 'primereact', 'primevue',\n 'element-plus', 'element-ui',\n 'semantic-ui-react', 'semantic-ui-css',\n 'rsuite', 'blueprint', '@blueprintjs/core',\n 'react-aria-components', 'ariakit',\n 'flowbite', 'flowbite-react', 'daisyui',\n 'mantine', '@mantine/core', '@mantine/hooks',\n '@mantine/form', '@mantine/notifications',\n 'shadcn-ui', 'cmdk',\n\n // ---------------------------------------------------------------------------\n // Image processing\n // ---------------------------------------------------------------------------\n 'sharp', 'jimp', 'canvas', 'fabric',\n 'pngjs', 'jpeg-js', 'bmp-js',\n 'image-size', 'probe-image-size',\n 'gm', 'imagemin', 'imagemin-pngquant', 'imagemin-mozjpeg',\n 'responsive-loader', 'next-optimized-images',\n 'blurhash', 'plaiceholder',\n 'qrcode', 'jsqr', 'bwip-js',\n 'pica', 'cropperjs', 'react-cropper',\n 'exif-parser', 'piexifjs',\n 'svg-captcha', 'svgo', 'svg-parser',\n '@svgr/core', '@svgr/webpack',\n\n // ---------------------------------------------------------------------------\n // Email / messaging\n // ---------------------------------------------------------------------------\n 'nodemailer', 'nodemailer-sendgrid-transport',\n '@sendgrid/mail', '@sendgrid/client',\n 'mailgun-js', '@mailgun/mailgun-js',\n 'postmark', '@postmark/postmark',\n 'email-templates', 'mjml',\n 'react-email', '@react-email/components',\n 'juice', 'html-to-text',\n 'twilio', 'vonage', '@vonage/server-sdk',\n 'firebase-admin', 'web-push', 'onesignal-node',\n '@slack/web-api', '@slack/bolt',\n 'discord.js', 'telegraf', 'node-telegram-bot-api',\n 'whatsapp-web.js',\n\n // ---------------------------------------------------------------------------\n // Cloud SDKs — AWS\n // ---------------------------------------------------------------------------\n 'aws-sdk', '@aws-sdk/client-s3', '@aws-sdk/client-dynamodb',\n '@aws-sdk/client-sqs', '@aws-sdk/client-sns',\n '@aws-sdk/client-lambda', '@aws-sdk/client-ses',\n '@aws-sdk/client-iam', '@aws-sdk/client-ec2',\n '@aws-sdk/client-ecs', '@aws-sdk/client-cloudformation',\n '@aws-sdk/client-cloudwatch', '@aws-sdk/client-secrets-manager',\n '@aws-sdk/client-ssm', '@aws-sdk/client-sts',\n '@aws-sdk/client-cognito-identity-provider',\n '@aws-sdk/client-kms', '@aws-sdk/client-kinesis',\n '@aws-sdk/lib-dynamodb', '@aws-sdk/s3-request-presigner',\n '@aws-sdk/credential-providers', '@aws-sdk/smithy-client',\n 'aws-amplify', '@aws-amplify/ui-react',\n 'serverless', 'serverless-offline', 'serverless-webpack',\n 'aws-cdk-lib', 'constructs',\n 'sst', '@serverless-stack/resources',\n\n // ---------------------------------------------------------------------------\n // Cloud SDKs — GCP\n // ---------------------------------------------------------------------------\n '@google-cloud/storage', '@google-cloud/firestore',\n '@google-cloud/pubsub', '@google-cloud/bigquery',\n '@google-cloud/functions-framework', '@google-cloud/logging',\n '@google-cloud/secret-manager', '@google-cloud/tasks',\n '@google-cloud/translate', '@google-cloud/vision',\n '@google-cloud/text-to-speech', '@google-cloud/speech',\n 'firebase', 'firebase-admin', 'firebase-functions',\n 'firebase-tools', '@firebase/app', '@firebase/auth',\n '@firebase/firestore', '@firebase/storage',\n 'googleapis', 'google-auth-library',\n\n // ---------------------------------------------------------------------------\n // Cloud SDKs — Azure / misc cloud\n // ---------------------------------------------------------------------------\n '@azure/storage-blob', '@azure/identity', '@azure/keyvault-secrets',\n '@azure/cosmos', '@azure/service-bus', '@azure/event-hubs',\n '@azure/functions', '@azure/msal-node', '@azure/msal-browser',\n '@azure/msal-react', '@azure/core-rest-pipeline',\n 'supabase', '@supabase/supabase-js', '@supabase/auth-helpers-nextjs',\n 'cloudflare', '@cloudflare/workers-types', 'wrangler',\n 'vercel', '@vercel/analytics', '@vercel/og', '@vercel/kv',\n 'netlify-cli', '@netlify/functions',\n 'digitalocean', 'heroku',\n\n // ---------------------------------------------------------------------------\n // Monitoring / APM / error tracking\n // ---------------------------------------------------------------------------\n '@sentry/node', '@sentry/browser', '@sentry/react',\n '@sentry/nextjs', '@sentry/vue', '@sentry/tracing',\n 'newrelic', '@newrelic/native-metrics',\n 'prom-client', 'express-prom-bundle',\n 'elastic-apm-node', '@elastic/apm-rum',\n 'dd-trace', 'hot-shots',\n '@opentelemetry/api', '@opentelemetry/sdk-node',\n '@opentelemetry/sdk-trace-node', '@opentelemetry/exporter-trace-otlp-http',\n '@opentelemetry/instrumentation-http', '@opentelemetry/instrumentation-express',\n 'applicationinsights', 'raygun', 'bugsnag',\n '@bugsnag/js', '@bugsnag/plugin-react',\n 'rollbar', 'logrocket', 'posthog-js', 'posthog-node',\n 'clinic', 'autocannon', '0x',\n\n // ---------------------------------------------------------------------------\n // Caching\n // ---------------------------------------------------------------------------\n 'node-cache', 'lru-cache', 'quick-lru', 'tiny-lru',\n 'keyv', '@keyv/redis', '@keyv/mongo',\n 'cacheable-request', 'apicache',\n 'memcached', 'catbox', '@hapi/catbox-redis',\n 'flat-cache', 'file-system-cache', 'cache-manager',\n 'stale-while-revalidate-cache',\n\n // ---------------------------------------------------------------------------\n // Queue / job processing\n // ---------------------------------------------------------------------------\n 'bull', 'bullmq', 'bee-queue', 'agenda',\n 'amqplib', 'amqp-connection-manager',\n 'kafkajs', 'node-rdkafka',\n 'celery-node', 'rsmq', 'sqs-consumer',\n 'p-queue', 'p-limit', 'p-map', 'p-retry', 'p-throttle',\n 'p-all', 'p-settle', 'p-props', 'p-event',\n 'async', 'neo-async', 'fastq',\n 'cron', 'node-cron', 'node-schedule', 'later',\n 'bree', 'croner',\n\n // ---------------------------------------------------------------------------\n // Serialization / schema / data formats\n // ---------------------------------------------------------------------------\n 'protobufjs', 'google-protobuf', '@grpc/grpc-js', '@grpc/proto-loader',\n 'avro-js', 'avsc',\n 'msgpack', 'msgpack-lite', '@msgpack/msgpack',\n 'flatbuffers', 'cbor', 'bson',\n 'yaml', 'js-yaml', 'toml', '@iarna/toml',\n 'ini', 'json5', 'jsonc-parser', 'strip-json-comments',\n 'qs', 'query-string', 'querystring', 'url-parse',\n 'form-data', 'formdata-polyfill', 'multipart-parser',\n\n // ---------------------------------------------------------------------------\n // Date / time\n // ---------------------------------------------------------------------------\n 'date-fns', 'date-fns-tz', 'dayjs', 'moment', 'moment-timezone',\n 'luxon', 'ms', 'humanize-duration', 'pretty-ms',\n 'chrono-node', 'spacetime', 'timeago.js',\n '@internationalized/date', 'fecha', 'dateformat',\n 'rrule',\n\n // ---------------------------------------------------------------------------\n // Math / science / numbers\n // ---------------------------------------------------------------------------\n 'mathjs', 'decimal.js', 'bignumber.js', 'big.js',\n 'bn.js', 'fraction.js', 'currency.js',\n 'dinero.js', 'accounting', 'numeral',\n 'd3-scale', 'd3-array', 'd3-format',\n 'simple-statistics', 'regression', 'ml-regression',\n 'seedrandom', 'chance',\n\n // ---------------------------------------------------------------------------\n // Compression\n // ---------------------------------------------------------------------------\n 'compression', 'pako', 'lz-string',\n 'lz4', 'snappy', 'brotli', 'iltorb',\n 'compressing', 'tar-stream', 'gunzip-maybe',\n 'archiver', 'unzipper', 'node-gzip',\n\n // ---------------------------------------------------------------------------\n // Networking / DNS / low-level\n // ---------------------------------------------------------------------------\n 'dns-packet', 'dns-over-http', 'native-dns',\n 'ip', 'ip-address', 'cidr-matcher', 'ipaddr.js',\n 'mac-address', 'public-ip', 'internal-ip',\n 'is-online', 'is-reachable', 'ping', 'tcp-ping',\n 'net-ping', 'raw-socket', 'pcap',\n 'socks', 'socks-proxy-agent', 'https-proxy-agent',\n 'http-proxy-agent', 'pac-proxy-agent', 'proxy-agent',\n 'tunnel', 'global-agent', 'agent-base',\n 'ssh2', 'node-ssh',\n 'ftp', 'basic-ftp', 'ssh2-sftp-client',\n\n // ---------------------------------------------------------------------------\n // Package managers / monorepo tools\n // ---------------------------------------------------------------------------\n 'npm', 'yarn', 'pnpm', 'bun',\n 'lerna', 'nx', '@nrwl/workspace', '@nrwl/react', '@nrwl/node',\n 'changesets', '@changesets/cli', '@changesets/changelog-github',\n 'rush', '@microsoft/rush', 'bolt',\n 'syncpack', 'ultra-runner', 'wireit',\n 'verdaccio', 'npm-registry-fetch', 'pacote',\n 'np', 'release-it', 'semantic-release', 'standard-version',\n 'auto', 'bumpp', 'publish-please',\n\n // ---------------------------------------------------------------------------\n // Documentation\n // ---------------------------------------------------------------------------\n 'typedoc', 'jsdoc', 'documentation',\n 'docusaurus', '@docusaurus/core', '@docusaurus/preset-classic',\n 'vuepress', 'vitepress', 'docsify', 'docsify-cli',\n 'storybook', 'swagger-ui-express', 'swagger-jsdoc',\n 'redoc', 'spectaql', 'apidoc',\n 'compodoc', 'esdoc',\n\n // ---------------------------------------------------------------------------\n // Internationalization (i18n)\n // ---------------------------------------------------------------------------\n 'i18next', 'react-i18next', 'i18next-http-backend',\n 'i18next-browser-languagedetector', 'i18next-fs-backend',\n 'vue-i18n', '@nuxtjs/i18n',\n 'react-intl', '@formatjs/intl', '@formatjs/cli',\n 'globalize', 'messageformat', 'gettext-parser',\n 'polyglot', 'lingui', '@lingui/core', '@lingui/react',\n 'rosetta', 'typesafe-i18n',\n 'intl-messageformat', 'intl-pluralrules',\n\n // ---------------------------------------------------------------------------\n // Accessibility\n // ---------------------------------------------------------------------------\n 'axe-core', '@axe-core/react', '@axe-core/playwright',\n 'pa11y', 'pa11y-ci', 'lighthouse',\n 'eslint-plugin-jsx-a11y', 'react-axe',\n 'ally.js', 'focus-trap', 'focus-trap-react', 'focus-visible',\n 'aria-query', 'dom-accessibility-api',\n\n // ---------------------------------------------------------------------------\n // Editor / rich text\n // ---------------------------------------------------------------------------\n 'prosemirror-state', 'prosemirror-view', 'prosemirror-model',\n 'prosemirror-transform', 'prosemirror-commands',\n 'tiptap', '@tiptap/core', '@tiptap/react', '@tiptap/vue-3',\n '@tiptap/starter-kit', '@tiptap/extension-link',\n 'slate', 'slate-react', 'slate-history',\n 'quill', 'react-quill', 'quill-delta',\n 'draft-js', 'draftjs-to-html', 'react-draft-wysiwyg',\n 'lexical', '@lexical/react',\n 'tinymce', '@tinymce/tinymce-react',\n 'ckeditor5', '@ckeditor/ckeditor5-react', '@ckeditor/ckeditor5-build-classic',\n 'codemirror', '@codemirror/state', '@codemirror/view',\n '@codemirror/lang-javascript', '@codemirror/lang-python',\n 'monaco-editor', '@monaco-editor/react',\n 'ace-builds', 'react-ace',\n 'editorjs', '@editorjs/editorjs',\n\n // ---------------------------------------------------------------------------\n // PDF / document generation\n // ---------------------------------------------------------------------------\n 'pdfkit', 'pdf-lib', 'pdfjs-dist', 'react-pdf',\n 'jspdf', 'jspdf-autotable', 'html2canvas', 'html2pdf.js',\n 'docx', 'officegen', 'xlsx', 'exceljs',\n 'pptxgenjs',\n 'latex.js', 'katex', 'mathjax',\n 'csv-writer', 'csv-stringify', 'fast-csv',\n\n // ---------------------------------------------------------------------------\n // Payment processing\n // ---------------------------------------------------------------------------\n 'stripe', '@stripe/stripe-js', '@stripe/react-stripe-js',\n 'paypal-rest-sdk', '@paypal/checkout-server-sdk',\n '@paypal/react-paypal-js', 'braintree', 'braintree-web',\n 'square', 'adyen-api', 'razorpay',\n 'coinbase-commerce-node', 'ethers', 'web3', 'web3-eth',\n '@solana/web3.js', 'bitcoinjs-lib',\n 'commerce.js', 'snipcart', 'medusa-core',\n\n // ---------------------------------------------------------------------------\n // Analytics\n // ---------------------------------------------------------------------------\n 'posthog-js', 'posthog-node',\n 'mixpanel', 'mixpanel-browser',\n 'amplitude-js', '@amplitude/analytics-browser',\n '@segment/analytics-next', 'analytics-node',\n 'matomo-tracker', 'plausible-tracker',\n 'react-ga', 'react-ga4', 'ga-4-react',\n 'universal-analytics', '@google-analytics/data',\n 'rudder-sdk-js',\n 'launchdarkly-node-server-sdk',\n 'statsig-node', 'growthbook', '@growthbook/growthbook-react',\n 'flagsmith', 'unleash-client',\n\n // ---------------------------------------------------------------------------\n // CMS / headless CMS\n // ---------------------------------------------------------------------------\n 'contentful', '@contentful/rich-text-react-renderer',\n 'strapi', '@strapi/strapi', '@strapi/plugin-users-permissions',\n 'sanity', '@sanity/client', '@sanity/image-url',\n 'directus', '@directus/sdk',\n 'ghost-admin-api', '@tryghost/content-api',\n 'prismic', '@prismicio/client', '@prismicio/react',\n 'storyblok-js-client', '@storyblok/react',\n 'keystone', '@keystone-6/core',\n 'payload', 'tinacms', 'decap-cms',\n 'wpapi',\n 'hygraph',\n\n // ---------------------------------------------------------------------------\n // SSR / SSG / meta-frameworks\n // ---------------------------------------------------------------------------\n 'eleventy', '@11ty/eleventy',\n 'hexo',\n 'gridsome', 'scully', '@scullyio/init',\n 'blitz', 'redwood', '@redwoodjs/core',\n 'fresh', 'analog',\n\n // ---------------------------------------------------------------------------\n // DevOps / Docker / CI-CD\n // ---------------------------------------------------------------------------\n 'dockerode', 'docker-compose',\n '@kubernetes/client-node',\n '@pulumi/aws', '@pulumi/gcp',\n '@actions/core', '@actions/github',\n '@actions/exec', '@actions/io', '@actions/cache',\n 'danger', 'semantic-release',\n 'env-ci', 'ci-info', 'is-ci',\n 'dotenv-vault', 'infisical',\n\n // ---------------------------------------------------------------------------\n // Scoped popular — @types/*\n // ---------------------------------------------------------------------------\n '@types/node', '@types/react', '@types/react-dom',\n '@types/jest', '@types/mocha', '@types/chai',\n '@types/express', '@types/lodash', '@types/underscore',\n '@types/uuid', '@types/validator', '@types/semver',\n '@types/jsonwebtoken', '@types/bcrypt', '@types/bcryptjs',\n '@types/cors', '@types/helmet', '@types/morgan',\n '@types/multer', '@types/busboy', '@types/formidable',\n '@types/fs-extra', '@types/glob', '@types/rimraf', '@types/mkdirp',\n '@types/ws', '@types/qs', '@types/cookie-parser',\n '@types/body-parser', '@types/compression', '@types/serve-static',\n '@types/supertest', '@types/sinon', '@types/debug',\n '@types/mime', '@types/mime-types',\n '@types/cheerio', '@types/jsdom', '@types/luxon',\n '@types/inquirer', '@types/yargs', '@types/minimist',\n '@types/shelljs', '@types/through2', '@types/pump',\n '@types/pug', '@types/ejs', '@types/mustache',\n '@types/js-yaml', '@types/ini', '@types/json5',\n '@types/escape-html', '@types/http-errors',\n '@types/http-proxy', '@types/http-proxy-middleware',\n '@types/connect', '@types/koa', '@types/koa-router',\n '@types/passport', '@types/passport-jwt', '@types/passport-local',\n '@types/sharp', '@types/canvas', '@types/d3',\n '@types/three', '@types/jquery', '@types/backbone',\n '@types/async', '@types/bluebird',\n '@types/nodemailer', '@types/pg', '@types/mysql',\n\n // ---------------------------------------------------------------------------\n // Scoped popular — @mui/* (Material UI)\n // ---------------------------------------------------------------------------\n '@mui/material', '@mui/icons-material', '@mui/system',\n '@mui/lab', '@mui/styles', '@mui/x-date-pickers',\n '@mui/x-data-grid', '@mui/base', '@mui/joy',\n\n // ---------------------------------------------------------------------------\n // Scoped popular — @tanstack/*\n // ---------------------------------------------------------------------------\n '@tanstack/react-query', '@tanstack/react-query-devtools',\n '@tanstack/react-table', '@tanstack/react-virtual',\n '@tanstack/react-router', '@tanstack/query-core',\n '@tanstack/vue-query', '@tanstack/solid-query',\n '@tanstack/react-form',\n\n // ---------------------------------------------------------------------------\n // Scoped popular — @nestjs/*\n // ---------------------------------------------------------------------------\n '@nestjs/core', '@nestjs/common', '@nestjs/platform-express',\n '@nestjs/swagger', '@nestjs/typeorm', '@nestjs/mongoose',\n '@nestjs/jwt', '@nestjs/passport', '@nestjs/config',\n '@nestjs/graphql', '@nestjs/microservices', '@nestjs/websockets',\n '@nestjs/testing', '@nestjs/cli', '@nestjs/cqrs',\n '@nestjs/bull', '@nestjs/schedule', '@nestjs/throttler',\n\n // ---------------------------------------------------------------------------\n // Scoped popular — @next/*, @reduxjs/*, @octokit/*, misc ecosystem\n // ---------------------------------------------------------------------------\n '@next/font', '@next/mdx', '@next/bundle-analyzer',\n '@next/env', '@next/eslint-plugin-next',\n\n '@reduxjs/toolkit',\n\n '@octokit/core', '@octokit/rest', '@octokit/graphql',\n '@octokit/auth-token', '@octokit/request',\n\n '@sindresorhus/is', '@sindresorhus/slugify',\n\n '@t3-oss/env-nextjs', '@t3-oss/env-core',\n\n // ---------------------------------------------------------------------------\n // Visualization / charting\n // ---------------------------------------------------------------------------\n 'd3', 'd3-selection', 'd3-scale', 'd3-shape', 'd3-axis',\n 'd3-transition', 'd3-geo', 'd3-hierarchy',\n 'chart.js', 'react-chartjs-2',\n 'echarts', 'echarts-for-react',\n 'three', '@react-three/fiber', '@react-three/drei',\n 'highcharts', 'highcharts-react-official',\n 'recharts', 'nivo', '@nivo/core', '@nivo/bar', '@nivo/line',\n 'victory', 'victory-core',\n 'plotly.js', 'react-plotly.js', 'vega', 'vega-lite',\n 'apexcharts', 'react-apexcharts',\n 'visx', '@visx/shape', '@visx/scale', '@visx/group',\n 'mapbox-gl', 'react-map-gl', 'leaflet', 'react-leaflet',\n '@deck.gl/core', '@deck.gl/react',\n 'ol', 'cesium', 'globe.gl',\n\n // ---------------------------------------------------------------------------\n // Forms / drag-and-drop\n // ---------------------------------------------------------------------------\n 'formik', 'react-hook-form', '@hookform/resolvers',\n 'final-form', 'react-final-form',\n 'react-jsonschema-form', '@rjsf/core',\n 'react-dnd', 'react-dnd-html5-backend',\n 'react-beautiful-dnd', '@dnd-kit/core', '@dnd-kit/sortable',\n 'sortablejs', 'vuedraggable', 'interact.js', 'dragula',\n\n // ---------------------------------------------------------------------------\n // Misc popular / low-level / legacy\n // ---------------------------------------------------------------------------\n 'bluebird', 'q', 'when', 'rsvp',\n 'async', 'neo-async',\n 'semver', 'yargs-parser',\n 'mime', 'mime-types', 'content-type', 'content-disposition',\n 'body-parser', 'cookie-parser', 'cookie', 'tough-cookie',\n 'compression', 'serve-static', 'serve-favicon',\n 'http-errors', 'on-finished', 'raw-body',\n 'path-to-regexp', 'path-parse', 'path-exists',\n 'string-width', 'strip-ansi', 'ansi-regex', 'ansi-styles',\n 'supports-color', 'has-flag', 'color-convert', 'color-name',\n 'resolve', 'resolve-from', 'resolve-cwd', 'enhanced-resolve',\n 'source-map', 'source-map-support', 'source-map-js',\n 'acorn', 'acorn-walk', 'espree', 'esprima',\n 'estree-walker', 'escodegen', 'recast', 'ast-types',\n 'magic-string', 'merge-stream', 'merge2',\n 'which', 'which-module', 'require-directory',\n 'require-main-filename', 'set-blocking',\n 'once', 'wrappy', 'inherits', 'util-deprecate',\n 'graceful-fs', 'jsonfile', 'universalify',\n 'lru-cache', 'yallist', 'minipass', 'minizlib',\n 'whatwg-url', 'tr46', 'webidl-conversions',\n 'iconv-lite', 'safer-buffer', 'string_decoder',\n 'node-gyp', 'node-pre-gyp', 'prebuild-install', 'prebuildify',\n 'nan', 'node-addon-api', 'napi-macros', 'bindings',\n 'env-paths', 'xdg-basedir', 'os-tmpdir', 'os-homedir',\n 'electron', 'electron-builder', 'electron-forge',\n 'electron-store', 'electron-updater',\n 'tauri', '@tauri-apps/api', '@tauri-apps/cli',\n 'react-native', 'expo', 'expo-cli', 'expo-router',\n '@react-native-community/cli', 'react-native-web',\n 'react-native-gesture-handler', 'react-native-reanimated',\n 'react-native-screens', 'react-native-safe-area-context',\n '@react-navigation/native', '@react-navigation/stack',\n '@react-navigation/bottom-tabs',\n 'nativescript', 'capacitor', '@capacitor/core', '@capacitor/cli',\n 'ionic', '@ionic/core', '@ionic/react', '@ionic/vue',\n\n // ---------------------------------------------------------------------------\n // jQuery / legacy frameworks\n // ---------------------------------------------------------------------------\n 'jquery', 'backbone', 'knockout', 'dojo',\n 'mootools', 'prototype', 'zepto',\n 'requirejs', 'systemjs', 'amd-loader',\n\n // ---------------------------------------------------------------------------\n // Deprecated / known-risky / compromised (useful for detection)\n // ---------------------------------------------------------------------------\n 'event-stream', 'flatmap-stream', 'node-uuid',\n 'coffee-script', 'coffeescript', 'bower',\n 'uglify-js', 'terser', 'clean-css',\n 'left-pad', 'is-promise', 'is-buffer',\n 'ua-parser-js', 'coa', 'rc', 'colors',\n 'node-ipc', 'peacenotwar', 'es5-ext',\n 'faker', 'request', 'tslint',\n 'node-pre-gyp', 'npm-lifecycle',\n] as const;\n\n// ---------------------------------------------------------------------------\n// TyposquatDetector\n// ---------------------------------------------------------------------------\n\nexport class TyposquatDetector {\n private readonly popularPackages: ReadonlySet<string>;\n private readonly popularList: readonly string[];\n\n constructor(extraPopularPackages?: string[]) {\n const combined = [...POPULAR_PACKAGES, ...(extraPopularPackages ?? [])];\n this.popularList = combined;\n this.popularPackages = new Set(combined);\n }\n\n /**\n * Async factory that creates a TyposquatDetector enriched with popular\n * packages fetched from the npm registry.\n *\n * The fetched list is cached locally (`~/.dep-oracle/popular-packages.json`)\n * with a 7-day TTL. If the fetch fails (offline, rate-limited, etc.) the\n * detector falls back to the hardcoded POPULAR_PACKAGES list only.\n *\n * Usage:\n * ```ts\n * const detector = await TyposquatDetector.createWithRegistry();\n * const result = detector.check('lod-ash');\n * ```\n */\n static async createWithRegistry(options?: {\n fetchPopular?: boolean;\n }): Promise<TyposquatDetector> {\n const shouldFetch = options?.fetchPopular ?? true;\n\n if (!shouldFetch) {\n return new TyposquatDetector();\n }\n\n const registryPackages = await fetchPopularPackages();\n return new TyposquatDetector(registryPackages);\n }\n\n /**\n * Check whether `packageName` looks like a typosquat of a popular package.\n * Returns risk assessment with details.\n */\n check(packageName: string): TyposquatResult {\n // If the package itself is a known popular package, it is safe\n if (this.popularPackages.has(packageName)) {\n return { isRisky: false, similarPackages: [], distance: 0 };\n }\n\n const similarPackages: string[] = [];\n let minDistance = Infinity;\n\n for (const popular of this.popularList) {\n const distance = levenshtein(packageName, popular);\n\n // Flag if Levenshtein distance is 1 or 2\n if (distance >= 1 && distance <= 2) {\n if (distance < minDistance) {\n minDistance = distance;\n }\n if (!similarPackages.includes(popular)) {\n similarPackages.push(popular);\n }\n }\n }\n\n // Also check common typosquat patterns even if Levenshtein > 2\n const patternMatches = this.checkTyposquatPatterns(packageName);\n for (const match of patternMatches) {\n if (!similarPackages.includes(match)) {\n similarPackages.push(match);\n const d = levenshtein(packageName, match);\n if (d < minDistance) {\n minDistance = d;\n }\n }\n }\n\n const isRisky = similarPackages.length > 0;\n\n return {\n isRisky,\n similarPackages: similarPackages.sort(),\n distance: isRisky ? minDistance : 0,\n };\n }\n\n // -------------------------------------------------------------------------\n // Pattern-based detection\n // -------------------------------------------------------------------------\n\n /**\n * Check for common typosquat patterns that may not be caught by\n * Levenshtein alone (e.g. adding -js, -node suffix).\n */\n private checkTyposquatPatterns(packageName: string): string[] {\n const matches: string[] = [];\n\n for (const popular of this.popularList) {\n // Skip exact matches\n if (packageName === popular) continue;\n\n // Pattern: added suffix (-js, -node, -lib, -pkg, -core)\n const suffixes = ['-js', '-node', '-lib', '-pkg', '-core', 'js', '-new'];\n for (const suffix of suffixes) {\n if (packageName === popular + suffix) {\n matches.push(popular);\n break;\n }\n if (packageName + suffix === popular) {\n matches.push(popular);\n break;\n }\n }\n\n // Pattern: doubled letters (e.g. \"expresss\" vs \"express\")\n if (this.isDoubledLetter(packageName, popular)) {\n matches.push(popular);\n continue;\n }\n\n // Pattern: missing letter (e.g. \"expres\" vs \"express\")\n if (this.isMissingLetter(packageName, popular)) {\n matches.push(popular);\n continue;\n }\n\n // Pattern: transposed adjacent letters (e.g. \"exrpess\" vs \"express\")\n if (this.isTransposed(packageName, popular)) {\n matches.push(popular);\n continue;\n }\n\n // Pattern: homoglyph / common substitution (e.g. \"1odash\" vs \"lodash\")\n if (this.isHomoglyph(packageName, popular)) {\n matches.push(popular);\n continue;\n }\n }\n\n return matches;\n }\n\n /**\n * Check if `input` is `target` with one letter doubled.\n * e.g. \"expresss\" -> \"express\"\n */\n private isDoubledLetter(input: string, target: string): boolean {\n if (input.length !== target.length + 1) return false;\n\n let skipped = false;\n let j = 0;\n for (let i = 0; i < input.length; i++) {\n if (j >= target.length) {\n // Extra char at end — check it is the same as previous\n if (!skipped && i > 0 && input[i] === input[i - 1]) return true;\n return false;\n }\n if (input[i] === target[j]) {\n j++;\n } else if (!skipped && i > 0 && input[i] === input[i - 1]) {\n skipped = true;\n // Don't advance j — this is the doubled letter\n } else {\n return false;\n }\n }\n return j === target.length;\n }\n\n /**\n * Check if `input` is `target` with one letter removed.\n * e.g. \"expres\" -> \"express\"\n */\n private isMissingLetter(input: string, target: string): boolean {\n if (input.length !== target.length - 1) return false;\n\n let skipped = false;\n let j = 0;\n for (let i = 0; i < target.length; i++) {\n if (j >= input.length) {\n return !skipped;\n }\n if (input[j] === target[i]) {\n j++;\n } else if (!skipped) {\n skipped = true;\n // Skip this target char\n } else {\n return false;\n }\n }\n return j === input.length;\n }\n\n /**\n * Check if `input` is `target` with two adjacent letters swapped.\n * e.g. \"exrpess\" -> \"express\"\n */\n private isTransposed(input: string, target: string): boolean {\n if (input.length !== target.length) return false;\n\n let diffCount = 0;\n let firstDiff = -1;\n\n for (let i = 0; i < input.length; i++) {\n if (input[i] !== target[i]) {\n diffCount++;\n if (diffCount === 1) {\n firstDiff = i;\n } else if (diffCount === 2) {\n // Check if this is a transposition of adjacent characters\n if (\n i === firstDiff + 1 &&\n input[firstDiff] === target[i] &&\n input[i] === target[firstDiff]\n ) {\n // Valid transposition — continue checking the rest\n } else {\n return false;\n }\n } else {\n return false;\n }\n }\n }\n\n return diffCount === 2;\n }\n\n /**\n * Check for common character substitutions (homoglyphs).\n * e.g. \"1odash\" vs \"lodash\", \"rn\" vs \"m\"\n */\n private isHomoglyph(input: string, target: string): boolean {\n if (input.length !== target.length) return false;\n\n const substitutions: Record<string, string[]> = {\n 'l': ['1', 'i', '|'],\n 'o': ['0'],\n '0': ['o'],\n '1': ['l', 'i'],\n 'i': ['1', 'l'],\n 'e': ['3'],\n 's': ['5'],\n 'a': ['4', '@'],\n 'g': ['9'],\n 'b': ['6'],\n };\n\n let subCount = 0;\n\n for (let i = 0; i < input.length; i++) {\n if (input[i] !== target[i]) {\n const allowed = substitutions[target[i]];\n if (allowed && allowed.includes(input[i])) {\n subCount++;\n if (subCount > 2) return false; // Allow up to 2 substitutions\n } else {\n return false;\n }\n }\n }\n\n return subCount >= 1 && subCount <= 2;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Levenshtein distance\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the Levenshtein (edit) distance between two strings.\n * Uses the classic dynamic-programming approach with O(min(m,n)) space.\n */\nfunction levenshtein(a: string, b: string): number {\n // Ensure `a` is the shorter string for space optimization\n if (a.length > b.length) {\n [a, b] = [b, a];\n }\n\n const m = a.length;\n const n = b.length;\n\n // Edge cases\n if (m === 0) return n;\n if (n === 0) return m;\n\n // Previous and current row of distances\n let prev = new Array<number>(m + 1);\n let curr = new Array<number>(m + 1);\n\n // Initialize the base row\n for (let i = 0; i <= m; i++) {\n prev[i] = i;\n }\n\n for (let j = 1; j <= n; j++) {\n curr[0] = j;\n\n for (let i = 1; i <= m; i++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n curr[i] = Math.min(\n prev[i] + 1, // deletion\n curr[i - 1] + 1, // insertion\n prev[i - 1] + cost, // substitution\n );\n }\n\n // Swap rows\n [prev, curr] = [curr, prev];\n }\n\n return prev[m];\n}\n","// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type MigrationDifficulty = 'easy' | 'moderate' | 'hard';\n\nexport interface MigrationSuggestion {\n /** Name of the alternative package. */\n alternative: string;\n /** Short description of the alternative and migration path. */\n description: string;\n /** Estimated difficulty of migrating to this alternative. */\n difficulty: MigrationDifficulty;\n}\n\n/** Internal entry in the migration map. */\ninterface MigrationEntry {\n alternative: string;\n description: string;\n difficulty: MigrationDifficulty;\n}\n\n// ---------------------------------------------------------------------------\n// Migration map — hardcoded knowledge base of common replacements\n// ---------------------------------------------------------------------------\n\nconst MIGRATION_MAP: Record<string, MigrationEntry[]> = {\n // Date/time libraries\n 'moment': [\n {\n alternative: 'dayjs',\n description: 'Lightweight Moment.js alternative with compatible API. Drop-in replacement for most use cases.',\n difficulty: 'easy',\n },\n {\n alternative: 'date-fns',\n description: 'Modular date utility library. Tree-shakeable, functional API. Requires rewriting date manipulation calls.',\n difficulty: 'moderate',\n },\n {\n alternative: 'luxon',\n description: 'Modern date/time library by a Moment.js maintainer. Immutable, chainable API with timezone support.',\n difficulty: 'moderate',\n },\n ],\n\n // HTTP client libraries\n 'request': [\n {\n alternative: 'got',\n description: 'Feature-rich HTTP client with retry, pagination, and stream support. Promise-based API.',\n difficulty: 'moderate',\n },\n {\n alternative: 'axios',\n description: 'Popular HTTP client for browser and Node.js. Interceptors, transforms, and cancellation support.',\n difficulty: 'easy',\n },\n {\n alternative: 'node-fetch',\n description: 'Lightweight Fetch API implementation for Node.js. Minimal API surface.',\n difficulty: 'moderate',\n },\n {\n alternative: 'undici',\n description: 'Official Node.js HTTP/1.1 client. High performance, built into Node 18+.',\n difficulty: 'moderate',\n },\n ],\n\n // Color/terminal output\n 'colors': [\n {\n alternative: 'chalk',\n description: 'Most popular terminal string styling library. Clean, chainable API.',\n difficulty: 'easy',\n },\n {\n alternative: 'picocolors',\n description: 'Tiny (< 3KB) terminal color library. Fastest option, no dependencies.',\n difficulty: 'easy',\n },\n {\n alternative: 'colorette',\n description: 'Lightweight terminal color library. Similar API to picocolors.',\n difficulty: 'easy',\n },\n ],\n\n // Compromised packages\n 'event-stream': [\n {\n alternative: 'highland',\n description: 'High-level stream library. Manages backpressure and provides functional stream composition.',\n difficulty: 'moderate',\n },\n {\n alternative: 'through2',\n description: 'Thin wrapper around Node.js streams. Simple transform/writable stream creation.',\n difficulty: 'easy',\n },\n ],\n\n // Utility belts\n 'underscore': [\n {\n alternative: 'lodash',\n description: 'Superset of underscore functionality. Drop-in replacement with better performance.',\n difficulty: 'easy',\n },\n {\n alternative: 'ramda',\n description: 'Functional programming utility library. Curried by default, immutable data focus.',\n difficulty: 'hard',\n },\n ],\n\n 'lodash': [\n {\n alternative: 'es-toolkit',\n description: 'Modern TypeScript utility library. Drop-in replacement for common lodash functions, tree-shakeable.',\n difficulty: 'easy',\n },\n {\n alternative: 'ramda',\n description: 'Functional programming utility library. Different paradigm — curried, point-free style.',\n difficulty: 'hard',\n },\n {\n alternative: 'radash',\n description: 'Modern lodash alternative with TypeScript-first design. Smaller bundle, zero dependencies.',\n difficulty: 'moderate',\n },\n ],\n\n // Build tools\n 'bower': [\n {\n alternative: 'npm',\n description: 'Default Node.js package manager. Bower is deprecated — migrate packages to npm.',\n difficulty: 'hard',\n },\n {\n alternative: 'yarn',\n description: 'Alternative package manager with workspaces. Bower packages need to be republished.',\n difficulty: 'hard',\n },\n ],\n\n // Language / transpilers\n 'coffee-script': [\n {\n alternative: 'typescript',\n description: 'Typed superset of JavaScript. Industry standard, excellent tooling support.',\n difficulty: 'hard',\n },\n ],\n 'coffeescript': [\n {\n alternative: 'typescript',\n description: 'Typed superset of JavaScript. Industry standard, excellent tooling support.',\n difficulty: 'hard',\n },\n ],\n\n // Minifiers\n 'uglify-js': [\n {\n alternative: 'terser',\n description: 'Fork of uglify-es with ES6+ support. Drop-in replacement for most configurations.',\n difficulty: 'easy',\n },\n {\n alternative: 'esbuild',\n description: 'Extremely fast bundler and minifier written in Go. 10-100x faster than terser.',\n difficulty: 'moderate',\n },\n ],\n\n // UUID generation\n 'node-uuid': [\n {\n alternative: 'uuid',\n description: 'Official successor package. Same maintainers, just renamed. Direct drop-in replacement.',\n difficulty: 'easy',\n },\n ],\n\n // Code coverage\n 'istanbul': [\n {\n alternative: 'nyc',\n description: 'Istanbul CLI wrapper. Easier configuration and integration with test runners.',\n difficulty: 'easy',\n },\n {\n alternative: 'c8',\n description: 'Native V8 code coverage. Uses built-in Node.js coverage, no instrumentation needed.',\n difficulty: 'easy',\n },\n ],\n\n // Linting\n 'tslint': [\n {\n alternative: 'eslint',\n description: 'TSLint is deprecated. Use ESLint with @typescript-eslint/parser for TypeScript linting.',\n difficulty: 'moderate',\n },\n ],\n\n // Promise libraries\n 'bluebird': [\n {\n alternative: 'native-promises',\n description: 'Native Promise API is now performant enough for most use cases. Remove bluebird and use built-in Promise.',\n difficulty: 'moderate',\n },\n ],\n\n // Test runners\n 'mocha': [\n {\n alternative: 'vitest',\n description: 'Vite-native test runner. Fast, ESM-first, Jest-compatible API. Built-in coverage and watch mode.',\n difficulty: 'moderate',\n },\n {\n alternative: 'jest',\n description: 'Zero-config testing framework. Snapshot testing, mocking, and coverage built in.',\n difficulty: 'moderate',\n },\n ],\n\n // Callback utilities\n 'async': [\n {\n alternative: 'p-map',\n description: 'Promise-based concurrent mapping. Use with async/await for cleaner control flow.',\n difficulty: 'moderate',\n },\n {\n alternative: 'p-limit',\n description: 'Promise-based concurrency limiter. Modern replacement for async.parallelLimit.',\n difficulty: 'easy',\n },\n ],\n\n // Legacy HTTP frameworks\n 'restify': [\n {\n alternative: 'fastify',\n description: 'High-performance web framework. Schema-based validation, plugin architecture.',\n difficulty: 'moderate',\n },\n {\n alternative: 'express',\n description: 'Most popular Node.js web framework. Large ecosystem, extensive middleware.',\n difficulty: 'moderate',\n },\n ],\n\n 'hapi': [\n {\n alternative: 'fastify',\n description: 'High-performance alternative with similar plugin architecture. Built-in validation and serialization.',\n difficulty: 'moderate',\n },\n ],\n\n // Template engines\n 'jade': [\n {\n alternative: 'pug',\n description: 'Jade was renamed to Pug. Same syntax, same maintainers. Update the package name.',\n difficulty: 'easy',\n },\n ],\n\n // Glob / file matching\n 'glob': [\n {\n alternative: 'fast-glob',\n description: 'Faster glob implementation. Returns promises by default, supports negation patterns.',\n difficulty: 'easy',\n },\n {\n alternative: 'globby',\n description: 'User-friendly glob matching built on fast-glob. Supports gitignore and multiple patterns.',\n difficulty: 'easy',\n },\n ],\n\n // Deprecated request-related\n 'superagent': [\n {\n alternative: 'got',\n description: 'Modern HTTP client with better error handling, retry support, and TypeScript types.',\n difficulty: 'moderate',\n },\n {\n alternative: 'undici',\n description: 'Official Node.js HTTP client. Built into Node 18+, high performance.',\n difficulty: 'moderate',\n },\n ],\n\n // Process management\n 'nodemon': [\n {\n alternative: 'tsx',\n description: 'TypeScript execute with watch mode. Built on esbuild, instant restarts.',\n difficulty: 'easy',\n },\n ],\n\n // Shortid (deprecated)\n 'shortid': [\n {\n alternative: 'nanoid',\n description: 'Smaller, faster, URL-safe unique ID generator. Drop-in replacement, better entropy.',\n difficulty: 'easy',\n },\n {\n alternative: 'cuid',\n description: 'Collision-resistant unique IDs. Designed for horizontal scaling and security.',\n difficulty: 'easy',\n },\n ],\n\n // Crypto\n 'crypto-js': [\n {\n alternative: 'node:crypto',\n description: 'Built-in Node.js crypto module. No external dependency, maintained by Node.js core team.',\n difficulty: 'moderate',\n },\n ],\n\n // Body parsing (standalone)\n 'body-parser': [\n {\n alternative: 'express',\n description: 'body-parser is built into Express 4.16+. Use express.json() and express.urlencoded() directly.',\n difficulty: 'easy',\n },\n ],\n\n // YAML\n 'js-yaml': [\n {\n alternative: 'yaml',\n description: 'Full YAML 1.2 support with better error messages and TypeScript types.',\n difficulty: 'easy',\n },\n ],\n\n // Rimraf\n 'rimraf': [\n {\n alternative: 'fs.rm',\n description: 'Built-in Node.js fs.rm with recursive option (Node 14.14+). No external dependency needed.',\n difficulty: 'easy',\n },\n ],\n\n // Mkdirp\n 'mkdirp': [\n {\n alternative: 'fs.mkdir',\n description: 'Built-in Node.js fs.mkdir with recursive option (Node 10.12+). No external dependency needed.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // left-pad (infamous, now unnecessary)\n // ---------------------------------------------------------------------------\n 'left-pad': [\n {\n alternative: 'String.prototype.padStart',\n description: 'Built-in ES2017 String method. Native replacement, zero dependencies.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // querystring (deprecated Node.js built-in)\n // ---------------------------------------------------------------------------\n 'querystring': [\n {\n alternative: 'URLSearchParams',\n description: 'Web-standard URL query string API built into Node.js. Handles encoding/decoding correctly.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // request-promise / request-promise-native (deprecated with request)\n // ---------------------------------------------------------------------------\n 'request-promise': [\n {\n alternative: 'got',\n description: 'Modern HTTP client with native Promise support, retries, and hooks. request is fully deprecated.',\n difficulty: 'moderate',\n },\n {\n alternative: 'axios',\n description: 'Promise-based HTTP client for Node.js and browsers. Familiar interceptor API.',\n difficulty: 'easy',\n },\n {\n alternative: 'undici',\n description: 'Official Node.js HTTP client built into Node 18+. High performance, standards-based.',\n difficulty: 'moderate',\n },\n ],\n\n 'request-promise-native': [\n {\n alternative: 'got',\n description: 'Modern HTTP client with native Promise support. No wrapper needed, request is deprecated.',\n difficulty: 'moderate',\n },\n {\n alternative: 'undici',\n description: 'Official Node.js HTTP client built into Node 18+. Standards-based fetch API.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // node-sass (deprecated in favor of Dart Sass)\n // ---------------------------------------------------------------------------\n 'node-sass': [\n {\n alternative: 'sass',\n description: 'Dart Sass is the primary implementation of Sass. node-sass is deprecated. API is compatible for most use cases.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // PhantomJS (abandoned)\n // ---------------------------------------------------------------------------\n 'phantomjs': [\n {\n alternative: 'playwright',\n description: 'Modern browser automation by Microsoft. Supports Chromium, Firefox, and WebKit. Actively maintained.',\n difficulty: 'hard',\n },\n {\n alternative: 'puppeteer',\n description: 'Chrome/Chromium automation by Google. Headless browser testing and scraping.',\n difficulty: 'hard',\n },\n ],\n\n 'phantomjs-prebuilt': [\n {\n alternative: 'playwright',\n description: 'Modern browser automation supporting multiple browsers. PhantomJS is abandoned and insecure.',\n difficulty: 'hard',\n },\n {\n alternative: 'puppeteer',\n description: 'Headless Chrome automation. Direct replacement for PhantomJS browser scripting use cases.',\n difficulty: 'hard',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // merge (unmaintained shallow merge)\n // ---------------------------------------------------------------------------\n 'merge': [\n {\n alternative: 'deepmerge',\n description: 'Deep merge utility with support for arrays, Maps, and Sets. Actively maintained.',\n difficulty: 'easy',\n },\n {\n alternative: 'lodash.merge',\n description: 'Well-tested deep merge from lodash. Handles circular references and complex objects.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // minimatch (old versions with ReDoS)\n // ---------------------------------------------------------------------------\n 'minimatch': [\n {\n alternative: 'picomatch',\n description: 'Fast and accurate glob matcher. Better performance and no ReDoS vulnerabilities.',\n difficulty: 'easy',\n },\n {\n alternative: 'micromatch',\n description: 'Feature-rich glob matcher built on picomatch. Supports extended globs and brace expansion.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // har-validator (deprecated)\n // ---------------------------------------------------------------------------\n 'har-validator': [\n {\n alternative: 'har-schema',\n description: 'Use the HAR schema directly with ajv or zod for validation. har-validator is unmaintained.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // graphql-tools (old monolithic Apollo package)\n // ---------------------------------------------------------------------------\n 'graphql-tools': [\n {\n alternative: '@graphql-tools/schema',\n description: 'Modular GraphQL Tools packages. Import only what you need from the scoped @graphql-tools/* packages.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // enzyme (React testing, abandoned)\n // ---------------------------------------------------------------------------\n 'enzyme': [\n {\n alternative: '@testing-library/react',\n description: 'Testing Library encourages testing user behavior instead of implementation details. React recommended approach.',\n difficulty: 'hard',\n },\n ],\n\n 'enzyme-adapter-react-16': [\n {\n alternative: '@testing-library/react',\n description: 'Enzyme adapters are no longer maintained for newer React. Testing Library works with all React versions.',\n difficulty: 'hard',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // sinon (test doubles)\n // ---------------------------------------------------------------------------\n 'sinon': [\n {\n alternative: 'vitest',\n description: 'Vitest includes built-in vi.fn(), vi.spyOn(), and vi.mock() for mocking. No separate library needed.',\n difficulty: 'moderate',\n },\n {\n alternative: 'jest',\n description: 'Jest includes built-in jest.fn(), jest.spyOn(), and jest.mock(). No separate mocking library needed.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // karma (test runner for browsers)\n // ---------------------------------------------------------------------------\n 'karma': [\n {\n alternative: 'vitest',\n description: 'Fast Vite-native test runner with browser mode. Replaces Karma for both unit and browser testing.',\n difficulty: 'hard',\n },\n {\n alternative: 'jest',\n description: 'Zero-config test framework with jsdom for DOM testing. No browser process required.',\n difficulty: 'hard',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // jasmine\n // ---------------------------------------------------------------------------\n 'jasmine': [\n {\n alternative: 'vitest',\n description: 'Modern test runner with Jest-compatible API. Faster execution, ESM support, built-in coverage.',\n difficulty: 'moderate',\n },\n {\n alternative: 'jest',\n description: 'Feature-rich test framework. Similar describe/it syntax, built-in mocking and assertions.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // tape\n // ---------------------------------------------------------------------------\n 'tape': [\n {\n alternative: 'vitest',\n description: 'Modern test runner with a rich assertion API. Supports TAP output via reporters if needed.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // ava\n // ---------------------------------------------------------------------------\n 'ava': [\n {\n alternative: 'vitest',\n description: 'Vitest offers similar parallel test execution with better IDE integration and watch mode.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // nyc (Istanbul CLI)\n // ---------------------------------------------------------------------------\n 'nyc': [\n {\n alternative: 'c8',\n description: 'Native V8 code coverage using NODE_V8_COVERAGE. No instrumentation, faster and more accurate.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // node-fetch / cross-fetch / isomorphic-fetch (native fetch in Node 18+)\n // ---------------------------------------------------------------------------\n 'node-fetch': [\n {\n alternative: 'native fetch',\n description: 'Node.js 18+ includes a global fetch() based on undici. No polyfill needed for modern Node.',\n difficulty: 'easy',\n },\n ],\n\n 'cross-fetch': [\n {\n alternative: 'native fetch',\n description: 'Node.js 18+ and all modern browsers support fetch() natively. Polyfill no longer needed.',\n difficulty: 'easy',\n },\n ],\n\n 'isomorphic-fetch': [\n {\n alternative: 'native fetch',\n description: 'Global fetch() is available in Node.js 18+ and all modern browsers. Remove the polyfill.',\n difficulty: 'easy',\n },\n ],\n\n 'isomorphic-unfetch': [\n {\n alternative: 'native fetch',\n description: 'Minimal fetch polyfill no longer needed. Node.js 18+ ships native fetch globally.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // express-validator\n // ---------------------------------------------------------------------------\n 'express-validator': [\n {\n alternative: 'zod',\n description: 'TypeScript-first schema validation. Framework-agnostic, composable schemas, great type inference.',\n difficulty: 'moderate',\n },\n {\n alternative: 'valibot',\n description: 'Tiny, tree-shakeable schema validation library. Similar API to zod with smaller bundle size.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // cls-hooked (async context)\n // ---------------------------------------------------------------------------\n 'cls-hooked': [\n {\n alternative: 'AsyncLocalStorage',\n description: 'Built-in Node.js AsyncLocalStorage (stable since Node 16). No external dependency for async context propagation.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // dotenv\n // ---------------------------------------------------------------------------\n 'dotenv': [\n {\n alternative: 'node --env-file',\n description: 'Node.js 20.6+ supports --env-file flag natively. No library needed for .env loading.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // chalk (for simple coloring)\n // ---------------------------------------------------------------------------\n 'chalk': [\n {\n alternative: 'picocolors',\n description: 'Tiny (< 3KB), dependency-free terminal color library. 2x faster than chalk, covers most use cases.',\n difficulty: 'easy',\n },\n {\n alternative: 'colorette',\n description: 'Lightweight terminal coloring. Simple API compatible with chalk basic usage patterns.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // commander / yargs (CLI argument parsing)\n // ---------------------------------------------------------------------------\n 'commander': [\n {\n alternative: 'citty',\n description: 'Elegant CLI builder from UnJS. TypeScript-first, minimal API with sub-command support.',\n difficulty: 'moderate',\n },\n {\n alternative: 'clipanion',\n description: 'Type-safe CLI framework used by Yarn. Advanced features like command routing and validation.',\n difficulty: 'moderate',\n },\n ],\n\n 'yargs': [\n {\n alternative: 'citty',\n description: 'Lightweight CLI builder from UnJS. Cleaner API, TypeScript types, smaller footprint than yargs.',\n difficulty: 'moderate',\n },\n {\n alternative: 'commander',\n description: 'Popular CLI framework with a simpler API. Less configuration overhead than yargs.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // inquirer / prompts (interactive CLI prompts)\n // ---------------------------------------------------------------------------\n 'inquirer': [\n {\n alternative: '@clack/prompts',\n description: 'Beautiful CLI prompts with minimal API. Better UX with spinners, grouping, and cancel handling.',\n difficulty: 'moderate',\n },\n ],\n\n 'prompts': [\n {\n alternative: '@clack/prompts',\n description: 'Modern interactive prompt library with better DX. Structured prompt flows with cancel support.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // listr (task runner)\n // ---------------------------------------------------------------------------\n 'listr': [\n {\n alternative: 'listr2',\n description: 'Actively maintained fork of listr. Better TypeScript support, new renderers, and task management.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Logging libraries\n // ---------------------------------------------------------------------------\n 'debug': [\n {\n alternative: 'pino',\n description: 'Fast structured JSON logger. Better for production observability than debug-style logging.',\n difficulty: 'moderate',\n },\n {\n alternative: 'consola',\n description: 'Elegant console logger from UnJS. Supports log levels, reporters, and structured output.',\n difficulty: 'easy',\n },\n ],\n\n 'bunyan': [\n {\n alternative: 'pino',\n description: 'Fastest Node.js JSON logger. Same structured JSON approach as bunyan, 5x faster.',\n difficulty: 'moderate',\n },\n ],\n\n 'log4js': [\n {\n alternative: 'pino',\n description: 'High-performance structured logger. Modern alternative to log4js with async I/O and transports.',\n difficulty: 'moderate',\n },\n ],\n\n 'signale': [\n {\n alternative: 'consola',\n description: 'Elegant console logger from UnJS. Beautiful output, pluggable reporters, TypeScript support.',\n difficulty: 'easy',\n },\n ],\n\n 'winston': [\n {\n alternative: 'pino',\n description: 'Significantly faster JSON logger. Simpler transport system, lower overhead in production.',\n difficulty: 'moderate',\n },\n ],\n\n 'morgan': [\n {\n alternative: 'pino-http',\n description: 'HTTP logger middleware for pino. Structured JSON request logging with automatic request IDs.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // ORM / Query builders\n // ---------------------------------------------------------------------------\n 'mongoose': [\n {\n alternative: 'prisma',\n description: 'Type-safe ORM with auto-generated client. Schema-first approach, migrations, and studio GUI.',\n difficulty: 'hard',\n },\n {\n alternative: 'drizzle-orm',\n description: 'Lightweight TypeScript ORM. SQL-like syntax, zero overhead, excellent type inference.',\n difficulty: 'hard',\n },\n ],\n\n 'sequelize': [\n {\n alternative: 'prisma',\n description: 'Modern type-safe ORM. Better TypeScript support, declarative schema, and migration tooling.',\n difficulty: 'hard',\n },\n {\n alternative: 'drizzle-orm',\n description: 'SQL-like TypeScript ORM. Closer to raw SQL than Sequelize, excellent performance.',\n difficulty: 'hard',\n },\n ],\n\n 'typeorm': [\n {\n alternative: 'prisma',\n description: 'More stable and actively maintained ORM. Better migration system and type safety.',\n difficulty: 'hard',\n },\n {\n alternative: 'drizzle-orm',\n description: 'Lightweight alternative with SQL-like API. Better TypeScript inference and query performance.',\n difficulty: 'hard',\n },\n ],\n\n 'knex': [\n {\n alternative: 'drizzle-orm',\n description: 'TypeScript-first query builder with ORM features. Similar SQL-like API with full type safety.',\n difficulty: 'moderate',\n },\n {\n alternative: 'kysely',\n description: 'Type-safe SQL query builder. End-to-end type safety from database schema to query results.',\n difficulty: 'moderate',\n },\n ],\n\n 'bookshelf': [\n {\n alternative: 'prisma',\n description: 'Modern ORM replacing Bookshelf/Knex stack. Auto-generated types, declarative relations, migrations.',\n difficulty: 'hard',\n },\n ],\n\n 'waterline': [\n {\n alternative: 'prisma',\n description: 'Sails.js ORM is rarely maintained. Prisma offers modern schema management and type safety.',\n difficulty: 'hard',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Authentication\n // ---------------------------------------------------------------------------\n 'passport': [\n {\n alternative: 'lucia-auth',\n description: 'Modern, lightweight auth library. Session-based authentication with clear API, no magic.',\n difficulty: 'hard',\n },\n {\n alternative: 'better-auth',\n description: 'Framework-agnostic TypeScript auth library. Built-in support for OAuth, email/password, and MFA.',\n difficulty: 'hard',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Password hashing\n // ---------------------------------------------------------------------------\n 'bcrypt': [\n {\n alternative: 'argon2',\n description: 'Winner of the Password Hashing Competition. More secure than bcrypt, resistant to GPU attacks.',\n difficulty: 'easy',\n },\n ],\n\n 'bcryptjs': [\n {\n alternative: 'argon2',\n description: 'Argon2 is the recommended password hashing algorithm. Better security profile than bcrypt variants.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Session management\n // ---------------------------------------------------------------------------\n 'express-session': [\n {\n alternative: 'iron-session',\n description: 'Encrypted stateless sessions using signed and encrypted cookies. No server-side session store needed.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // CORS / Security middleware\n // ---------------------------------------------------------------------------\n 'cors': [\n {\n alternative: 'helmet',\n description: 'Comprehensive security middleware that includes CORS handling along with other HTTP security headers.',\n difficulty: 'easy',\n },\n ],\n\n 'csurf': [\n {\n alternative: 'csrf-csrf',\n description: 'csurf is deprecated due to security issues. csrf-csrf implements the double-submit cookie pattern securely.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // File upload\n // ---------------------------------------------------------------------------\n 'multer': [\n {\n alternative: 'busboy',\n description: 'Low-level multipart parser. More control over file handling, better streaming support.',\n difficulty: 'moderate',\n },\n {\n alternative: 'formidable',\n description: 'Full-featured form/file parser. Streaming, plugins, and better memory management than multer.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // WebSocket\n // ---------------------------------------------------------------------------\n 'socket.io': [\n {\n alternative: 'ws',\n description: 'Lightweight WebSocket implementation. No protocol overhead, better for performance-critical applications.',\n difficulty: 'moderate',\n },\n {\n alternative: 'socket.io',\n description: 'If you need fallbacks and rooms, keep socket.io but upgrade to v4+ for improved performance.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // HTTP clients (alternatives to axios/got)\n // ---------------------------------------------------------------------------\n 'axios': [\n {\n alternative: 'ky',\n description: 'Tiny HTTP client built on fetch. Simpler API, automatic retries, hooks, and smaller bundle.',\n difficulty: 'moderate',\n },\n {\n alternative: 'ofetch',\n description: 'Universal fetch client from UnJS. Works in Node, browser, and workers with auto-parsing.',\n difficulty: 'moderate',\n },\n ],\n\n 'got': [\n {\n alternative: 'ofetch',\n description: 'Lightweight universal fetch from UnJS. Simpler API with auto-retry, auto-parse, and type safety.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Job scheduling / queues\n // ---------------------------------------------------------------------------\n 'node-cron': [\n {\n alternative: 'croner',\n description: 'Modern cron scheduler with timezone support, overrun protection, and better pattern parsing.',\n difficulty: 'easy',\n },\n ],\n\n 'agenda': [\n {\n alternative: 'bullmq',\n description: 'Redis-based job queue with better reliability. Supports delayed jobs, retries, and rate limiting.',\n difficulty: 'moderate',\n },\n ],\n\n 'bull': [\n {\n alternative: 'bullmq',\n description: 'Next generation of Bull by the same author. Better TypeScript support, flows, and worker threads.',\n difficulty: 'moderate',\n },\n ],\n\n 'kue': [\n {\n alternative: 'bullmq',\n description: 'Kue is unmaintained. BullMQ is the modern Redis-based queue with job scheduling and retries.',\n difficulty: 'moderate',\n },\n ],\n\n 'bee-queue': [\n {\n alternative: 'bullmq',\n description: 'BullMQ offers more features than bee-queue: job flows, rate limiting, and better error handling.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Redis clients\n // ---------------------------------------------------------------------------\n 'redis': [\n {\n alternative: 'ioredis',\n description: 'Full-featured Redis client with cluster support, Lua scripting, and pipelining. Better performance.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // MongoDB native driver\n // ---------------------------------------------------------------------------\n 'mongodb': [\n {\n alternative: 'mongoose',\n description: 'Schema-based ODM for MongoDB. Adds validation, middleware, and population to raw driver.',\n difficulty: 'moderate',\n },\n {\n alternative: 'prisma',\n description: 'Type-safe ORM with MongoDB support. Auto-generated client, declarative schema.',\n difficulty: 'hard',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // memcached\n // ---------------------------------------------------------------------------\n 'memcached': [\n {\n alternative: 'ioredis',\n description: 'Redis is a superset of memcached features with persistence, pub/sub, and data structures.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Build tools / bundlers\n // ---------------------------------------------------------------------------\n 'webpack': [\n {\n alternative: 'vite',\n description: 'Next-gen frontend build tool. Instant dev server with HMR, Rollup-based production builds.',\n difficulty: 'hard',\n },\n {\n alternative: 'rspack',\n description: 'Rust-based webpack-compatible bundler. Drop-in replacement with 5-10x build speed improvement.',\n difficulty: 'moderate',\n },\n ],\n\n 'rollup': [\n {\n alternative: 'vite',\n description: 'Vite uses Rollup under the hood for production. Better DX with dev server and plugin ecosystem.',\n difficulty: 'moderate',\n },\n ],\n\n 'parcel': [\n {\n alternative: 'vite',\n description: 'Similar zero-config philosophy with better plugin ecosystem and community support.',\n difficulty: 'moderate',\n },\n ],\n\n 'gulp': [\n {\n alternative: 'npm scripts',\n description: 'Replace gulp tasks with npm scripts in package.json. Use concurrently for parallel tasks.',\n difficulty: 'moderate',\n },\n {\n alternative: 'vite',\n description: 'Modern build tool that replaces custom gulp build pipelines. Plugin-based, zero-config defaults.',\n difficulty: 'hard',\n },\n ],\n\n 'grunt': [\n {\n alternative: 'npm scripts',\n description: 'Replace Grunt tasks with npm scripts. Modern tooling eliminates the need for task runners.',\n difficulty: 'moderate',\n },\n ],\n\n 'browserify': [\n {\n alternative: 'vite',\n description: 'Modern bundler with ESM-first approach. Replaces browserify with faster builds and HMR.',\n difficulty: 'hard',\n },\n {\n alternative: 'esbuild',\n description: 'Extremely fast JavaScript bundler. Simple API, handles CommonJS and ESM bundling.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Transpilers / TypeScript execution\n // ---------------------------------------------------------------------------\n 'babel': [\n {\n alternative: 'swc',\n description: 'Rust-based JavaScript/TypeScript compiler. 20x faster than Babel, compatible plugin API.',\n difficulty: 'moderate',\n },\n {\n alternative: 'esbuild',\n description: 'Go-based transpiler and bundler. Handles JSX, TypeScript, and modern JS transforms.',\n difficulty: 'moderate',\n },\n ],\n\n '@babel/core': [\n {\n alternative: 'swc',\n description: 'Rust-based compiler. Drop-in replacement for most Babel configurations, dramatically faster.',\n difficulty: 'moderate',\n },\n {\n alternative: 'esbuild',\n description: 'Extremely fast transpiler. Handles TypeScript, JSX, and most modern JS features.',\n difficulty: 'moderate',\n },\n ],\n\n 'ts-node': [\n {\n alternative: 'tsx',\n description: 'TypeScript execute powered by esbuild. Instant startup, ESM support, watch mode included.',\n difficulty: 'easy',\n },\n ],\n\n 'ts-jest': [\n {\n alternative: 'vitest',\n description: 'Vite-native test runner with built-in TypeScript support. No separate transformer needed.',\n difficulty: 'moderate',\n },\n {\n alternative: '@swc/jest',\n description: 'SWC-based Jest transformer. 10x faster TypeScript compilation than ts-jest.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Email\n // ---------------------------------------------------------------------------\n 'nodemailer': [\n {\n alternative: 'resend',\n description: 'Modern email API built for developers. Simple SDK, React Email support, better deliverability.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Template engines\n // ---------------------------------------------------------------------------\n 'nunjucks': [\n {\n alternative: 'edge.js',\n description: 'Modern template engine for Node.js. Better error messages, tag-based components, TypeScript support.',\n difficulty: 'moderate',\n },\n {\n alternative: 'eta',\n description: 'Lightweight, fast template engine. Supports async, partials, and configurable syntax.',\n difficulty: 'moderate',\n },\n ],\n\n 'ejs': [\n {\n alternative: 'eta',\n description: 'Faster and lighter EJS alternative. Compatible syntax with better async support and security.',\n difficulty: 'easy',\n },\n ],\n\n 'pug': [\n {\n alternative: 'edge.js',\n description: 'Modern tag-based template engine. Cleaner syntax, better error reporting, component support.',\n difficulty: 'moderate',\n },\n ],\n\n 'handlebars': [\n {\n alternative: 'edge.js',\n description: 'Modern template engine with better control flow. No need for custom helpers for basic logic.',\n difficulty: 'moderate',\n },\n {\n alternative: 'eta',\n description: 'Lightweight template engine with configurable delimiters. Supports async and partials.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Markdown\n // ---------------------------------------------------------------------------\n 'marked': [\n {\n alternative: 'markdown-it',\n description: 'Pluggable Markdown parser. Better extensibility, CommonMark compliance, and plugin ecosystem.',\n difficulty: 'easy',\n },\n {\n alternative: '@mdx-js/mdx',\n description: 'MDX enables JSX in Markdown. Ideal for content-driven apps with interactive components.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // DOM parsing / manipulation\n // ---------------------------------------------------------------------------\n 'cheerio': [\n {\n alternative: 'linkedom',\n description: 'Fast, lightweight DOM implementation. Standards-compliant, smaller bundle, better performance.',\n difficulty: 'moderate',\n },\n ],\n\n 'jsdom': [\n {\n alternative: 'happy-dom',\n description: 'Faster alternative to jsdom. 2-3x performance improvement, good compatibility with testing libraries.',\n difficulty: 'easy',\n },\n {\n alternative: 'linkedom',\n description: 'Lightweight DOM implementation. Faster than jsdom with smaller memory footprint.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Browser automation / E2E testing\n // ---------------------------------------------------------------------------\n 'puppeteer': [\n {\n alternative: 'playwright',\n description: 'Multi-browser automation (Chrome, Firefox, WebKit). Better auto-wait, tracing, and test generation.',\n difficulty: 'moderate',\n },\n ],\n\n 'cypress': [\n {\n alternative: 'playwright',\n description: 'Multi-browser E2E testing. Faster execution, better parallelization, and cross-browser support.',\n difficulty: 'hard',\n },\n ],\n\n 'selenium-webdriver': [\n {\n alternative: 'playwright',\n description: 'Modern browser automation with auto-wait and multi-browser support. No WebDriver protocol overhead.',\n difficulty: 'hard',\n },\n ],\n\n 'webdriverio': [\n {\n alternative: 'playwright',\n description: 'Simpler API with built-in assertions. No WebDriver dependency, faster test execution.',\n difficulty: 'hard',\n },\n ],\n\n 'protractor': [\n {\n alternative: 'playwright',\n description: 'Protractor is deprecated. Playwright supports Angular apps and offers modern test tooling.',\n difficulty: 'hard',\n },\n ],\n\n 'nightmare': [\n {\n alternative: 'playwright',\n description: 'Nightmare is unmaintained. Playwright offers reliable browser automation across all modern browsers.',\n difficulty: 'hard',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Image processing\n // ---------------------------------------------------------------------------\n 'sharp': [\n {\n alternative: '@napi-rs/image',\n description: 'Rust-based image processing via N-API. No native dependency issues, cross-platform binaries.',\n difficulty: 'moderate',\n },\n ],\n\n 'jimp': [\n {\n alternative: 'sharp',\n description: 'libvips-based image processor. 10x faster than jimp for resizing, converting, and transforming images.',\n difficulty: 'moderate',\n },\n ],\n\n 'gm': [\n {\n alternative: 'sharp',\n description: 'No external GraphicsMagick/ImageMagick install required. Faster processing with libvips.',\n difficulty: 'moderate',\n },\n ],\n\n 'imagemagick': [\n {\n alternative: 'sharp',\n description: 'Native Node.js image processing without system dependency. Faster and easier to deploy.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Timezone / Date utilities\n // ---------------------------------------------------------------------------\n 'moment-timezone': [\n {\n alternative: 'luxon',\n description: 'Built-in IANA timezone support via Intl API. No separate timezone data bundle needed.',\n difficulty: 'moderate',\n },\n {\n alternative: 'date-fns-tz',\n description: 'Timezone support for date-fns. Modular, tree-shakeable, uses native Intl API.',\n difficulty: 'moderate',\n },\n ],\n\n 'chrono-node': [\n {\n alternative: 'date-fns',\n description: 'Comprehensive date utility library. Use date-fns/parse for structured date parsing.',\n difficulty: 'moderate',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Promise libraries (legacy)\n // ---------------------------------------------------------------------------\n 'q': [\n {\n alternative: 'native promises',\n description: 'Native Promise/async-await is standard since ES2015. Remove Q and use built-in Promise API.',\n difficulty: 'moderate',\n },\n ],\n\n 'when': [\n {\n alternative: 'native promises',\n description: 'Native Promise with async/await covers all when.js use cases. No polyfill library needed.',\n difficulty: 'moderate',\n },\n ],\n\n 'rsvp': [\n {\n alternative: 'native promises',\n description: 'RSVP is no longer needed. Native Promise API is performant and universally supported.',\n difficulty: 'moderate',\n },\n ],\n\n 'es6-promise': [\n {\n alternative: 'native promises',\n description: 'ES6 Promise polyfill is unnecessary. All supported Node.js versions have native Promise.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // String similarity\n // ---------------------------------------------------------------------------\n 'string-similarity': [\n {\n alternative: 'fastest-levenshtein',\n description: 'Fastest Levenshtein distance implementation. Better performance for string comparison use cases.',\n difficulty: 'easy',\n },\n ],\n\n 'leven': [\n {\n alternative: 'fastest-levenshtein',\n description: 'Faster Levenshtein distance calculation with the same simple API.',\n difficulty: 'easy',\n },\n ],\n\n // ---------------------------------------------------------------------------\n // Additional commonly encountered packages\n // ---------------------------------------------------------------------------\n 'request-promise-any': [\n {\n alternative: 'got',\n description: 'Modern HTTP client with promise support. request ecosystem is fully deprecated.',\n difficulty: 'moderate',\n },\n ],\n\n 'uuid': [\n {\n alternative: 'crypto.randomUUID',\n description: 'Built-in Node.js 19+ and Web Crypto API. No dependency needed for UUID v4 generation.',\n difficulty: 'easy',\n },\n ],\n\n 'form-data': [\n {\n alternative: 'native FormData',\n description: 'Node.js 18+ includes global FormData. No polyfill needed for modern Node versions.',\n difficulty: 'easy',\n },\n ],\n\n 'node-abort-controller': [\n {\n alternative: 'native AbortController',\n description: 'AbortController is global in Node.js 16+. Remove the polyfill package.',\n difficulty: 'easy',\n },\n ],\n\n 'object-assign': [\n {\n alternative: 'Object.assign / spread',\n description: 'Native Object.assign() and spread syntax are available in all modern environments.',\n difficulty: 'easy',\n },\n ],\n\n 'array-flatten': [\n {\n alternative: 'Array.prototype.flat',\n description: 'Native Array.flat() is available since ES2019. No utility package needed.',\n difficulty: 'easy',\n },\n ],\n\n 'string.prototype.trimstart': [\n {\n alternative: 'String.prototype.trimStart',\n description: 'Native trimStart() is available since ES2019. Remove the polyfill.',\n difficulty: 'easy',\n },\n ],\n\n 'string.prototype.trimend': [\n {\n alternative: 'String.prototype.trimEnd',\n description: 'Native trimEnd() is available since ES2019. Remove the polyfill.',\n difficulty: 'easy',\n },\n ],\n};\n\n// ---------------------------------------------------------------------------\n// MigrationAdvisor\n// ---------------------------------------------------------------------------\n\nexport class MigrationAdvisor {\n private readonly migrationMap: Record<string, MigrationEntry[]>;\n\n constructor(extraMappings?: Record<string, MigrationEntry[]>) {\n this.migrationMap = { ...MIGRATION_MAP, ...extraMappings };\n }\n\n /**\n * Look up migration suggestions for a given package.\n *\n * @param packageName - The npm package to find alternatives for.\n * @param reason - Why the migration is being suggested (e.g. \"zombie\", \"low trust score\").\n * This is included in the description for context.\n * @returns Array of migration suggestions, empty if no known alternatives exist.\n */\n suggest(packageName: string, reason: string): MigrationSuggestion[] {\n const normalized = packageName.toLowerCase().trim();\n const entries = this.migrationMap[normalized];\n\n if (!entries || entries.length === 0) {\n return [];\n }\n\n return entries.map((entry) => ({\n alternative: entry.alternative,\n description: `${entry.description} (Reason for migration: ${reason})`,\n difficulty: entry.difficulty,\n }));\n }\n\n /**\n * Check whether any migration suggestions exist for a package.\n */\n hasSuggestions(packageName: string): boolean {\n const normalized = packageName.toLowerCase().trim();\n return normalized in this.migrationMap;\n }\n\n /**\n * Return the list of all packages that have known migration paths.\n */\n getSupportedPackages(): string[] {\n return Object.keys(this.migrationMap).sort();\n }\n}\n"],"mappings":"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","names":["readFile","access","join","fileExists","access","readText","readFile","readJson","join","join","monthsBetween","readFile","join","readFileSync","writeFileSync","mkdirSync","existsSync","join","homedir","CACHE_DIR","join","homedir","existsSync","readFileSync","mkdirSync","writeFileSync"]}