@yabasha/gex 0.3.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -55,15 +55,20 @@ Common options:
55
55
  Examples:
56
56
 
57
57
  ```bash
58
- # Local (default): JSON stdout or to default file if -f provided without -o
59
- gex # same as: gex local
60
- gex -f md -o report.md
58
+ # Local (default): JSON output to console
59
+ gex # prints JSON to console (same as: gex local)
60
+ gex -o report.json # writes JSON to file
61
+ gex -f md # prints markdown to console
62
+ gex -f md -o report.md # writes markdown to file
61
63
 
62
64
  # Local: exclude devDependencies
63
- gex local --omit-dev -f json -o deps.json
65
+ gex local --omit-dev # prints JSON to console
66
+ gex local --omit-dev -o deps.json # writes JSON to file
64
67
 
65
68
  # Global packages
66
- gex global -f md -o global.md
69
+ gex global # prints JSON to console
70
+ gex global -o global.json # writes JSON to file
71
+ gex global -f md # prints markdown to console
67
72
 
68
73
  # Read a previous report (JSON or Markdown)
69
74
  # Default prints names@versions; add -i to install
@@ -74,8 +79,14 @@ gex read -r path/to/report.json -i
74
79
  # Markdown
75
80
  gex read global.md
76
81
  gex read global.md -i
82
+
83
+ # Shell redirection (alternative to -o flag)
84
+ gex > report.json # redirect JSON output to file
85
+ gex global | jq '.global_packages' # pipe output to jq for processing
77
86
  ```
78
87
 
88
+ > **Note**: Starting from v0.4.0, GEX outputs to console by default instead of creating files automatically. Use the `-o/--out-file` flag to write to a file.
89
+
79
90
  ## JSON schema (summary)
80
91
 
81
92
  Top-level keys:
package/dist/cli.cjs CHANGED
@@ -431,10 +431,7 @@ function createLocalCommand(program) {
431
431
  const outFile = opts.outFile;
432
432
  const fullTree = Boolean(opts.fullTree);
433
433
  const omitDev = Boolean(opts.omitDev);
434
- let finalOutFile = outFile;
435
- if (!outFile && opts.outputFormat && typeof opts.outputFormat === "string") {
436
- finalOutFile = `gex-report.${outputFormat}`;
437
- }
434
+ const finalOutFile = outFile;
438
435
  const { report, markdownExtras } = await produceReport("local", {
439
436
  outputFormat,
440
437
  outFile: finalOutFile,
@@ -452,10 +449,7 @@ function createGlobalCommand(program) {
452
449
  const outputFormat = opts.outputFormat ?? "json";
453
450
  const outFile = opts.outFile;
454
451
  const fullTree = Boolean(opts.fullTree);
455
- let finalOutFile = outFile;
456
- if (!outFile && opts.outputFormat && typeof opts.outputFormat === "string") {
457
- finalOutFile = `gex-report.${outputFormat}`;
458
- }
452
+ const finalOutFile = outFile;
459
453
  const { report, markdownExtras } = await produceReport("global", {
460
454
  outputFormat,
461
455
  outFile: finalOutFile,
package/dist/cli.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/cli/commands.ts","../src/cli/install.ts","../src/cli/output.ts","../src/report/json.ts","../src/report/md.ts","../src/cli/parser.ts","../src/cli/report.ts","../src/npm.ts","../src/transform.ts","../src/cli/utils.ts"],"sourcesContent":["/**\n * @fileoverview Main CLI entry point for GEX dependency auditing tool\n */\n\nimport { createProgram } from './cli/commands.js'\n\n/**\n * Main CLI runner function\n *\n * @param argv - Command line arguments (defaults to process.argv)\n */\nexport async function run(argv = process.argv): Promise<void> {\n const program = await createProgram()\n await program.parseAsync(argv)\n}\n\nconst isMainModule = (() => {\n try {\n if (typeof require !== 'undefined' && typeof module !== 'undefined') {\n return (require as any).main === module\n }\n\n if (typeof import.meta !== 'undefined') {\n return import.meta.url === `file://${process.argv[1]}`\n }\n return false\n } catch {\n return false\n }\n})()\n\nif (isMainModule) {\n run().catch((error) => {\n console.error('CLI error:', error)\n process.exitCode = 1\n })\n}\n","/**\n * @fileoverview CLI command definitions and handlers\n */\n\nimport path from 'node:path'\n\nimport { Command } from 'commander'\n\nimport type { OutputFormat } from '../types.js'\n\nimport { installFromReport, printFromReport } from './install.js'\nimport { outputReport } from './output.js'\nimport { isMarkdownReportFile, loadReportFromFile } from './parser.js'\nimport { produceReport } from './report.js'\nimport { ASCII_BANNER, getToolVersion } from './utils.js'\n\n/**\n * Adds common options to a command\n *\n * @param cmd - Command to add options to\n * @param options - Configuration for which options to add\n * @returns Modified command\n */\nfunction addCommonOptions(cmd: Command, { allowOmitDev }: { allowOmitDev: boolean }): Command {\n cmd\n .option(\n '-f, --output-format <format>',\n 'Output format: md or json',\n (val) => (val === 'md' ? 'md' : 'json'),\n 'json',\n )\n .option('-o, --out-file <path>', 'Write report to file')\n .option('--full-tree', 'Include full npm ls tree (omit depth=0 default)', false)\n\n if (allowOmitDev) {\n cmd.option('--omit-dev', 'Exclude devDependencies (local only)', false)\n }\n\n return cmd\n}\n\n/**\n * Creates the local command handler\n *\n * @param program - Commander program instance\n * @returns Command instance\n */\nexport function createLocalCommand(program: Command): Command {\n const localCmd = program\n .command('local', { isDefault: true })\n .description(\"Generate a report for the current project's dependencies\")\n\n addCommonOptions(localCmd, { allowOmitDev: true })\n\n localCmd.action(async (opts) => {\n const outputFormat = (opts.outputFormat ?? 'json') as OutputFormat\n const outFile = opts.outFile as string | undefined\n const fullTree = Boolean(opts.fullTree)\n const omitDev = Boolean(opts.omitDev)\n\n let finalOutFile = outFile\n if (!outFile && opts.outputFormat && typeof opts.outputFormat === 'string') {\n finalOutFile = `gex-report.${outputFormat}`\n }\n\n const { report, markdownExtras } = await produceReport('local', {\n outputFormat,\n outFile: finalOutFile,\n fullTree,\n omitDev,\n })\n\n await outputReport(report, outputFormat, finalOutFile, markdownExtras)\n })\n\n return localCmd\n}\n\n/**\n * Creates the global command handler\n *\n * @param program - Commander program instance\n * @returns Command instance\n */\nexport function createGlobalCommand(program: Command): Command {\n const globalCmd = program\n .command('global')\n .description('Generate a report of globally installed packages')\n\n addCommonOptions(globalCmd, { allowOmitDev: false })\n\n globalCmd.action(async (opts) => {\n const outputFormat = (opts.outputFormat ?? 'json') as OutputFormat\n const outFile = opts.outFile as string | undefined\n const fullTree = Boolean(opts.fullTree)\n\n let finalOutFile = outFile\n if (!outFile && opts.outputFormat && typeof opts.outputFormat === 'string') {\n finalOutFile = `gex-report.${outputFormat}`\n }\n\n const { report, markdownExtras } = await produceReport('global', {\n outputFormat,\n outFile: finalOutFile,\n fullTree,\n })\n\n await outputReport(report, outputFormat, finalOutFile, markdownExtras)\n })\n\n return globalCmd\n}\n\n/**\n * Creates the read command handler\n *\n * @param program - Commander program instance\n * @returns Command instance\n */\nexport function createReadCommand(program: Command): Command {\n const readCmd = program\n .command('read')\n .description(\n 'Read a previously generated report (JSON or Markdown) and either print package names or install them',\n )\n .argument('[report]', 'Path to report file (JSON or Markdown)', 'gex-report.json')\n .option('-r, --report <path>', 'Path to report file (JSON or Markdown)')\n .option('-p, --print', 'Print package names/versions from the report (default)', false)\n .option('-i, --install', 'Install packages from the report', false)\n\n readCmd.action(async (reportArg: string | undefined, opts: any) => {\n const chosen = (opts.report as string | undefined) || reportArg || 'gex-report.json'\n const reportPath = path.resolve(process.cwd(), chosen)\n\n try {\n const parsed = await loadReportFromFile(reportPath)\n\n const doInstall = Boolean(opts.install)\n const doPrint = Boolean(opts.print) || !doInstall\n\n if (doPrint) {\n printFromReport(parsed)\n }\n if (doInstall) {\n await installFromReport(parsed, process.cwd())\n }\n } catch (err: any) {\n const isMd = isMarkdownReportFile(reportPath)\n const hint = isMd\n ? 'Try generating a JSON report with: gex global -f json -o global.json, then: gex read global.json'\n : 'Specify a report path with: gex read <path-to-report.json>'\n console.error(`Failed to read report at ${reportPath}: ${err?.message || err}`)\n console.error(hint)\n process.exitCode = 1\n }\n })\n\n return readCmd\n}\n\n/**\n * Creates and configures the main CLI program\n *\n * @returns Configured Commander program\n */\nexport async function createProgram(): Promise<Command> {\n const program = new Command()\n .name('gex')\n .description('GEX: Dependency auditing and documentation for Node.js (local and global).')\n .version(await getToolVersion())\n\n program.addHelpText('beforeAll', `\\n${ASCII_BANNER}`)\n\n createLocalCommand(program)\n createGlobalCommand(program)\n createReadCommand(program)\n\n return program\n}\n","/**\n * @fileoverview Package installation utilities for CLI\n */\n\nimport type { Report } from '../types.js'\n\n/**\n * Lazily obtain a promisified execFile so tests can mock built-ins reliably.\n */\nasync function getExecFileAsync(): Promise<\n (\n command: string,\n args?: readonly string[] | null,\n options?: any,\n ) => Promise<{ stdout: string; stderr: string }>\n> {\n const { execFile } = await import('node:child_process')\n const { promisify } = await import('node:util')\n return promisify(execFile) as any\n}\n\n/**\n * Installs packages from a report to the local environment\n *\n * @param report - The report containing packages to install\n * @param cwd - Current working directory for installation\n * @throws {Error} If npm installation fails\n */\nexport async function installFromReport(report: Report, cwd: string): Promise<void> {\n const globalPkgs = report.global_packages.map((p) => `${p.name}@${p.version}`).filter(Boolean)\n const localPkgs = report.local_dependencies.map((p) => `${p.name}@${p.version}`).filter(Boolean)\n const devPkgs = report.local_dev_dependencies.map((p) => `${p.name}@${p.version}`).filter(Boolean)\n\n if (globalPkgs.length === 0 && localPkgs.length === 0 && devPkgs.length === 0) {\n console.log('No packages to install from report.')\n return\n }\n\n // Acquire execFileAsync once per run to keep logs grouped, while still mockable in tests\n const execFileAsync = await getExecFileAsync()\n\n if (globalPkgs.length > 0) {\n console.log(`Installing global: ${globalPkgs.join(' ')}`)\n await execFileAsync('npm', ['i', '-g', ...globalPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 })\n }\n\n if (localPkgs.length > 0) {\n console.log(`Installing local deps: ${localPkgs.join(' ')}`)\n await execFileAsync('npm', ['i', ...localPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 })\n }\n\n if (devPkgs.length > 0) {\n console.log(`Installing local devDeps: ${devPkgs.join(' ')}`)\n await execFileAsync('npm', ['i', '-D', ...devPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 })\n }\n}\n\n/**\n * Prints packages from a report to the console\n *\n * @param report - The report to print packages from\n */\nexport function printFromReport(report: Report): void {\n const lines: string[] = []\n\n if (report.global_packages.length > 0) {\n lines.push('Global Packages:')\n for (const p of report.global_packages) {\n lines.push(`- ${p.name}@${p.version}`)\n }\n }\n\n if (report.local_dependencies.length > 0) {\n if (lines.length) lines.push('')\n lines.push('Local Dependencies:')\n for (const p of report.local_dependencies) {\n lines.push(`- ${p.name}@${p.version}`)\n }\n }\n\n if (report.local_dev_dependencies.length > 0) {\n if (lines.length) lines.push('')\n lines.push('Local Dev Dependencies:')\n for (const p of report.local_dev_dependencies) {\n lines.push(`- ${p.name}@${p.version}`)\n }\n }\n\n if (lines.length === 0) {\n lines.push('(no packages found in report)')\n }\n\n console.log(lines.join('\\n'))\n}\n","/**\n * @fileoverview Report output utilities for CLI\n */\n\nimport path from 'node:path'\n\nimport { renderJson } from '../report/json.js'\nimport { renderMarkdown } from '../report/md.js'\nimport type { OutputFormat, Report } from '../types.js'\n\n/**\n * Outputs a report to console or file\n *\n * @param report - The report to output\n * @param format - Output format ('json' or 'md')\n * @param outFile - Optional file path to write to\n * @param markdownExtras - Additional metadata for markdown rendering\n */\nexport async function outputReport(\n report: Report,\n format: OutputFormat,\n outFile?: string,\n markdownExtras?: any,\n): Promise<void> {\n const content =\n format === 'json'\n ? renderJson(report)\n : renderMarkdown({ ...report, ...(markdownExtras || {}) })\n\n if (outFile) {\n const outDir = path.dirname(outFile)\n const { mkdir, writeFile } = await import('node:fs/promises')\n\n await mkdir(outDir, { recursive: true })\n await writeFile(outFile, content, 'utf8')\n\n console.log(`Wrote report to ${outFile}`)\n } else {\n console.log(content)\n }\n}\n","/**\n * @fileoverview JSON report rendering utilities\n */\n\nimport type { Report } from '../types.js'\n\n/**\n * Renders a Report object as formatted JSON string\n *\n * @param report - Report object to render\n * @returns Pretty-printed JSON string with consistent package ordering\n *\n * @example\n * ```typescript\n * import { renderJson } from './report/json.js'\n *\n * const report = {\n * report_version: '1.0',\n * timestamp: new Date().toISOString(),\n * tool_version: '0.3.2',\n * global_packages: [],\n * local_dependencies: [{ name: 'axios', version: '1.6.0', resolved_path: '/path/to/axios' }],\n * local_dev_dependencies: []\n * }\n *\n * const jsonOutput = renderJson(report)\n * console.log(jsonOutput) // Pretty-printed JSON\n * ```\n */\nexport function renderJson(report: Report): string {\n const r: Report = {\n ...report,\n global_packages: [...report.global_packages].sort((a, b) => a.name.localeCompare(b.name)),\n local_dependencies: [...report.local_dependencies].sort((a, b) => a.name.localeCompare(b.name)),\n local_dev_dependencies: [...report.local_dev_dependencies].sort((a, b) =>\n a.name.localeCompare(b.name),\n ),\n }\n return JSON.stringify(r, null, 2)\n}\n","/**\n * @fileoverview Markdown report rendering utilities\n */\n\nimport type { Report } from '../types.js'\n\n/**\n * Creates a markdown table from headers and row data\n *\n * @param headers - Array of table header strings\n * @param rows - Array of row data (each row is array of strings)\n * @returns Formatted markdown table string\n */\nfunction table(headers: string[], rows: string[][]): string {\n const header = `| ${headers.join(' | ')} |`\n const sep = `| ${headers.map(() => '---').join(' | ')} |`\n const body = rows.map((r) => `| ${r.join(' | ')} |`).join('\\n')\n return [header, sep, body].filter(Boolean).join('\\n')\n}\n\n/**\n * Renders a Report object as formatted Markdown\n *\n * @param report - Report object with optional project metadata\n * @returns Formatted Markdown string with tables and sections\n *\n * @example\n * ```typescript\n * import { renderMarkdown } from './report/md.js'\n *\n * const report = {\n * report_version: '1.0',\n * timestamp: new Date().toISOString(),\n * tool_version: '0.3.2',\n * project_name: 'my-project',\n * global_packages: [],\n * local_dependencies: [\n * { name: 'axios', version: '1.6.0', resolved_path: '/path/to/axios' }\n * ],\n * local_dev_dependencies: [],\n * project_description: 'My awesome project'\n * }\n *\n * const markdown = renderMarkdown(report)\n * console.log(markdown) // Formatted markdown with tables\n * ```\n */\nexport function renderMarkdown(\n report: Report & {\n project_description?: string\n project_homepage?: string\n project_bugs?: string\n },\n): string {\n const lines: string[] = []\n lines.push('# GEX Report')\n lines.push('')\n\n if (\n report.project_name ||\n report.project_version ||\n (report as any).project_description ||\n (report as any).project_homepage ||\n (report as any).project_bugs\n ) {\n lines.push('## Project Metadata')\n if (report.project_name) lines.push(`- Name: ${report.project_name}`)\n if (report.project_version) lines.push(`- Version: ${report.project_version}`)\n if ((report as any).project_description)\n lines.push(`- Description: ${(report as any).project_description}`)\n if ((report as any).project_homepage)\n lines.push(`- Homepage: ${(report as any).project_homepage}`)\n if ((report as any).project_bugs) lines.push(`- Bugs: ${(report as any).project_bugs}`)\n lines.push('')\n }\n\n if (report.global_packages.length > 0) {\n lines.push('## Global Packages')\n const rows = report.global_packages.map((p) => [p.name, p.version || '', p.resolved_path || ''])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n if (report.local_dependencies.length > 0) {\n lines.push('## Local Dependencies')\n const rows = report.local_dependencies.map((p) => [\n p.name,\n p.version || '',\n p.resolved_path || '',\n ])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n if (report.local_dev_dependencies.length > 0) {\n lines.push('## Local Dev Dependencies')\n const rows = report.local_dev_dependencies.map((p) => [\n p.name,\n p.version || '',\n p.resolved_path || '',\n ])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n lines.push('---')\n lines.push('_Generated by GEX_')\n\n return lines.join('\\n')\n}\n","/**\n * @fileoverview Report parsing utilities for CLI\n */\n\nimport { readFile } from 'node:fs/promises'\nimport path from 'node:path'\n\nimport type { PackageInfo, Report } from '../types.js'\n\n/**\n * Checks if a file path indicates a markdown report\n */\nexport function isMarkdownReportFile(filePath: string): boolean {\n const ext = path.extname(filePath).toLowerCase()\n return ext === '.md' || ext === '.markdown'\n}\n\n/**\n * Parses a markdown table and extracts package information\n *\n * @param lines - Array of file lines\n * @param startIndex - Index where table starts\n * @returns Array of package information\n */\nfunction parseMarkdownPackagesTable(lines: string[], startIndex: number): PackageInfo[] {\n const rows: PackageInfo[] = []\n if (!lines[startIndex] || !lines[startIndex].trim().startsWith('|')) return rows\n\n let i = startIndex + 2\n while (i < lines.length && lines[i].trim().startsWith('|')) {\n const cols = lines[i]\n .split('|')\n .map((c) => c.trim())\n .filter((_, idx, arr) => !(idx === 0 || idx === arr.length - 1))\n\n const [name = '', version = '', resolved_path = ''] = cols\n if (name) rows.push({ name, version, resolved_path })\n i++\n }\n return rows\n}\n\n/**\n * Parses a markdown report and converts it to a Report object\n *\n * @param md - Markdown content to parse\n * @returns Parsed Report object\n */\nexport function parseMarkdownReport(md: string): Report {\n const lines = md.split(/\\r?\\n/)\n\n const findSection = (title: string) =>\n lines.findIndex((l) => l.trim().toLowerCase() === `## ${title}`.toLowerCase())\n\n const parseSection = (idx: number): PackageInfo[] => {\n if (idx < 0) return []\n\n let i = idx + 1\n while (i < lines.length && !lines[i].trim().startsWith('|')) i++\n return parseMarkdownPackagesTable(lines, i)\n }\n\n const global_packages = parseSection(findSection('Global Packages'))\n const local_dependencies = parseSection(findSection('Local Dependencies'))\n const local_dev_dependencies = parseSection(findSection('Local Dev Dependencies'))\n\n const report: Report = {\n report_version: '1.0',\n timestamp: new Date().toISOString(),\n tool_version: 'unknown',\n global_packages,\n local_dependencies,\n local_dev_dependencies,\n }\n return report\n}\n\n/**\n * Loads and parses a report file (JSON or Markdown)\n *\n * @param reportPath - Path to the report file\n * @returns Parsed Report object\n * @throws {Error} If file cannot be read or parsed\n */\nexport async function loadReportFromFile(reportPath: string): Promise<Report> {\n const raw = await readFile(reportPath, 'utf8')\n\n if (isMarkdownReportFile(reportPath) || raw.startsWith('# GEX Report')) {\n return parseMarkdownReport(raw)\n }\n\n return JSON.parse(raw) as Report\n}\n","/**\n * @fileoverview Report generation utilities for CLI\n */\n\nimport { readFile } from 'node:fs/promises'\nimport path from 'node:path'\n\nimport { npmLs, npmRootGlobal } from '../npm.js'\nimport { buildReportFromNpmTree } from '../transform.js'\nimport type { OutputFormat, Report } from '../types.js'\n\nimport { getToolVersion } from './utils.js'\n\n/**\n * Options for report generation\n */\nexport interface ReportOptions {\n outputFormat: OutputFormat\n outFile?: string\n fullTree?: boolean\n omitDev?: boolean\n cwd?: string\n}\n\n/**\n * Result of report generation including markdown extras\n */\nexport interface ReportResult {\n report: Report\n markdownExtras?: {\n project_description?: string\n project_homepage?: string\n project_bugs?: string\n }\n}\n\n/**\n * Produces a dependency report for local or global context\n *\n * @param ctx - Context for report generation ('local' or 'global')\n * @param options - Report generation options\n * @returns Report and optional markdown extras\n */\nexport async function produceReport(\n ctx: 'local' | 'global',\n options: ReportOptions,\n): Promise<ReportResult> {\n const toolVersion = await getToolVersion()\n const depth0 = !options.fullTree\n const cwd = options.cwd || process.cwd()\n\n const tree = await npmLs({\n global: ctx === 'global',\n omitDev: ctx === 'local' ? Boolean(options.omitDev) : false,\n depth0,\n cwd,\n })\n\n let project_description: string | undefined\n let project_homepage: string | undefined\n let project_bugs: string | undefined\n\n if (ctx === 'local') {\n try {\n const pkgRaw = await readFile(path.join(cwd, 'package.json'), 'utf8')\n const pkg = JSON.parse(pkgRaw)\n project_description = pkg.description\n project_homepage = pkg.homepage\n if (typeof pkg.bugs === 'string') project_bugs = pkg.bugs\n else if (pkg.bugs && typeof pkg.bugs.url === 'string') project_bugs = pkg.bugs.url\n } catch {\n // Ignore errors reading local package.json (e.g., file missing or invalid JSON)\n void 0\n }\n }\n\n const globalRoot = ctx === 'global' ? await npmRootGlobal().catch(() => undefined) : undefined\n\n const report = await buildReportFromNpmTree(tree, {\n context: ctx,\n includeTree: Boolean(options.fullTree),\n omitDev: Boolean(options.omitDev),\n cwd,\n toolVersion,\n globalRoot,\n })\n\n const markdownExtras = { project_description, project_homepage, project_bugs }\n return { report, markdownExtras }\n}\n","/**\n * @fileoverview npm command execution utilities for dependency analysis\n */\n\n/**\n * Lazily obtain a promisified execFile so tests can mock built-ins reliably.\n */\nasync function getExecFileAsync(): Promise<\n (\n command: string,\n args?: readonly string[] | null,\n options?: any,\n ) => Promise<{ stdout: string; stderr: string }>\n> {\n const { execFile } = await import('node:child_process')\n const { promisify } = await import('node:util')\n return promisify(execFile) as any\n}\n\n/**\n * Options for npm ls command execution\n */\nexport type NpmLsOptions = {\n /** Whether to list global packages */\n global?: boolean\n /** Whether to omit devDependencies */\n omitDev?: boolean\n /** Whether to use depth=0 for faster execution */\n depth0?: boolean\n /** Current working directory for command execution */\n cwd?: string\n}\n\n/**\n * Executes npm ls command and returns parsed dependency tree\n *\n * @param options - Configuration options for npm ls command\n * @returns Promise resolving to npm dependency tree object\n * @throws {Error} If npm command fails or output cannot be parsed\n *\n * @example\n * ```typescript\n * import { npmLs } from './npm.js'\n *\n * // Get local dependencies with devDependencies omitted\n * const tree = await npmLs({ omitDev: true, depth0: true })\n *\n * // Get global packages\n * const globalTree = await npmLs({ global: true })\n * ```\n */\nexport async function npmLs(options: NpmLsOptions = {}): Promise<any> {\n const args = ['ls', '--json']\n if (options.global) args.push('--global')\n if (options.omitDev) args.push('--omit=dev')\n if (options.depth0) args.push('--depth=0')\n\n try {\n const execFileAsync = await getExecFileAsync()\n const { stdout } = await execFileAsync('npm', args, {\n cwd: options.cwd,\n maxBuffer: 10 * 1024 * 1024,\n })\n if (stdout && stdout.trim()) return JSON.parse(stdout)\n return {}\n } catch (err: any) {\n const stdout = err?.stdout\n if (typeof stdout === 'string' && stdout.trim()) {\n try {\n return JSON.parse(stdout)\n } catch (parseErr) {\n if (process.env.DEBUG?.includes('gex')) {\n console.warn('npm ls stdout parse failed:', parseErr)\n }\n }\n }\n const stderr = err?.stderr\n const msg = (typeof stderr === 'string' && stderr.trim()) || err?.message || 'npm ls failed'\n throw new Error(`npm ls failed: ${msg}`)\n }\n}\n\n/**\n * Gets the global npm root directory path\n *\n * @returns Promise resolving to the global npm root path\n * @throws {Error} If npm root -g command fails\n *\n * @example\n * ```typescript\n * import { npmRootGlobal } from './npm.js'\n *\n * try {\n * const globalRoot = await npmRootGlobal()\n * console.log('Global npm root:', globalRoot)\n * } catch (error) {\n * console.error('Failed to get global root:', error.message)\n * }\n * ```\n */\nexport async function npmRootGlobal(): Promise<string> {\n try {\n const execFileAsync = await getExecFileAsync()\n const { stdout } = await execFileAsync('npm', ['root', '-g'])\n return stdout.trim()\n } catch (err: any) {\n const stderr = err?.stderr\n const msg =\n (typeof stderr === 'string' && stderr.trim()) || err?.message || 'npm root -g failed'\n throw new Error(`npm root -g failed: ${msg}`)\n }\n}\n","/**\n * @fileoverview Data transformation utilities for converting npm tree data into reports\n */\n\nimport path from 'node:path'\nimport { readFile } from 'node:fs/promises'\n\nimport type { PackageInfo, Report } from './types.js'\n\n/**\n * Options for report generation and normalization\n */\nexport type NormalizeOptions = {\n /** Context for report generation ('local' or 'global') */\n context: 'local' | 'global'\n /** Whether to include the full npm dependency tree */\n includeTree?: boolean\n /** Whether to omit devDependencies (local context only) */\n omitDev?: boolean\n /** Current working directory */\n cwd?: string\n /** Tool version to include in report */\n toolVersion: string\n /** Global npm root directory path */\n globalRoot?: string\n}\n\n/**\n * Converts npm dependency object to array of package entries\n *\n * @param obj - npm dependency object from npm ls output\n * @returns Array of name/node pairs for packages\n */\nfunction toPkgArray(obj: Record<string, any> | undefined | null): { name: string; node: any }[] {\n if (!obj) return []\n return Object.keys(obj)\n .map((name) => ({ name, node: obj[name] }))\n .filter((p) => p && p.node)\n}\n\n/**\n * Builds a GEX report from npm ls tree output\n *\n * @param tree - Raw npm ls command output\n * @param opts - Report generation options\n * @returns Promise resolving to a formatted Report object\n *\n * @example\n * ```typescript\n * import { buildReportFromNpmTree } from './transform.js'\n * import { npmLs } from './npm.js'\n *\n * const tree = await npmLs({ depth0: true })\n * const report = await buildReportFromNpmTree(tree, {\n * context: 'local',\n * toolVersion: '0.3.2',\n * cwd: process.cwd()\n * })\n *\n * console.log(`Found ${report.local_dependencies.length} dependencies`)\n * ```\n */\nexport async function buildReportFromNpmTree(tree: any, opts: NormalizeOptions): Promise<Report> {\n const timestamp = new Date().toISOString()\n const report: Report = {\n report_version: '1.0',\n timestamp,\n tool_version: opts.toolVersion,\n global_packages: [],\n local_dependencies: [],\n local_dev_dependencies: [],\n }\n\n if (opts.context === 'local') {\n let pkgMeta: any = null\n try {\n const pkgJsonPath = path.join(opts.cwd || process.cwd(), 'package.json')\n const raw = await readFile(pkgJsonPath, 'utf8')\n pkgMeta = JSON.parse(raw)\n } catch {\n // Ignore errors reading/parsing package.json; fall back to undefined metadata\n void 0\n }\n if (pkgMeta?.name) report.project_name = pkgMeta.name\n if (pkgMeta?.version) report.project_version = pkgMeta.version\n\n const depsObj = tree?.dependencies as Record<string, any> | undefined\n const items = toPkgArray(depsObj)\n const devKeys = new Set(Object.keys((pkgMeta?.devDependencies as Record<string, string>) || {}))\n\n for (const { name, node } of items) {\n const version = (node && node.version) || ''\n const resolvedPath =\n (node && node.path) || path.join(opts.cwd || process.cwd(), 'node_modules', name)\n const pkg: PackageInfo = { name, version, resolved_path: resolvedPath }\n if (devKeys.has(name)) {\n report.local_dev_dependencies.push(pkg)\n } else {\n report.local_dependencies.push(pkg)\n }\n }\n\n report.local_dependencies.sort((a, b) => a.name.localeCompare(b.name))\n report.local_dev_dependencies.sort((a, b) => a.name.localeCompare(b.name))\n } else if (opts.context === 'global') {\n const depsObj = tree?.dependencies as Record<string, any> | undefined\n const items = toPkgArray(depsObj)\n\n for (const { name, node } of items) {\n const version = (node && node.version) || ''\n const resolvedPath = (node && node.path) || path.join(opts.globalRoot || '', name)\n const pkg: PackageInfo = { name, version, resolved_path: resolvedPath }\n report.global_packages.push(pkg)\n }\n\n report.global_packages.sort((a, b) => a.name.localeCompare(b.name))\n }\n\n if (opts.includeTree) {\n report.tree = tree\n }\n\n return report\n}\n","/**\n * @fileoverview CLI utility functions for version handling and path resolution\n */\n\nimport { readFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\n/**\n * Gets the path to package.json for version resolution\n */\nexport function getPkgJsonPath(): string {\n try {\n const __filename = fileURLToPath((import.meta as any).url)\n const __dirnameLocal = path.dirname(__filename)\n return path.resolve(__dirnameLocal, '..', '..', 'package.json')\n } catch {\n const dir = typeof __dirname !== 'undefined' ? __dirname : process.cwd()\n return path.resolve(dir, '..', 'package.json')\n }\n}\n\n/**\n * Gets the current tool version from package.json\n */\nexport async function getToolVersion(): Promise<string> {\n try {\n const pkgPath = getPkgJsonPath()\n const raw = await readFile(pkgPath, 'utf8')\n const pkg = JSON.parse(raw)\n return pkg.version || '0.0.0'\n } catch {\n return '0.0.0'\n }\n}\n\n/**\n * ASCII banner for the CLI\n */\nexport const ASCII_BANNER = String.raw`\n ________ __\n / _____/ ____ _____/ |_ ____ ____\n/ \\ ___ / _ \\ / _ \\ __\\/ __ \\ / \\\n\\ \\_\\ ( <_> | <_> ) | \\ ___/| | \\\n \\______ /\\____/ \\____/|__| \\___ >___| /\n \\/ \\/ \\/\n GEX\n`\n"],"mappings":"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","names":["import_node_path","path","import_node_path","path","import_promises","import_node_path","getExecFileAsync","import_node_path","import_promises","path","import_promises","import_node_path","path","path","path","import_meta"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/cli/commands.ts","../src/cli/install.ts","../src/cli/output.ts","../src/report/json.ts","../src/report/md.ts","../src/cli/parser.ts","../src/cli/report.ts","../src/npm.ts","../src/transform.ts","../src/cli/utils.ts"],"sourcesContent":["/**\n * @fileoverview Main CLI entry point for GEX dependency auditing tool\n */\n\nimport { createProgram } from './cli/commands.js'\n\n/**\n * Main CLI runner function\n *\n * @param argv - Command line arguments (defaults to process.argv)\n */\nexport async function run(argv = process.argv): Promise<void> {\n const program = await createProgram()\n await program.parseAsync(argv)\n}\n\nconst isMainModule = (() => {\n try {\n if (typeof require !== 'undefined' && typeof module !== 'undefined') {\n return (require as any).main === module\n }\n\n if (typeof import.meta !== 'undefined') {\n return import.meta.url === `file://${process.argv[1]}`\n }\n return false\n } catch {\n return false\n }\n})()\n\nif (isMainModule) {\n run().catch((error) => {\n console.error('CLI error:', error)\n process.exitCode = 1\n })\n}\n","/**\n * @fileoverview CLI command definitions and handlers\n */\n\nimport path from 'node:path'\n\nimport { Command } from 'commander'\n\nimport type { OutputFormat } from '../types.js'\n\nimport { installFromReport, printFromReport } from './install.js'\nimport { outputReport } from './output.js'\nimport { isMarkdownReportFile, loadReportFromFile } from './parser.js'\nimport { produceReport } from './report.js'\nimport { ASCII_BANNER, getToolVersion } from './utils.js'\n\n/**\n * Adds common options to a command\n *\n * @param cmd - Command to add options to\n * @param options - Configuration for which options to add\n * @returns Modified command\n */\nfunction addCommonOptions(cmd: Command, { allowOmitDev }: { allowOmitDev: boolean }): Command {\n cmd\n .option(\n '-f, --output-format <format>',\n 'Output format: md or json',\n (val) => (val === 'md' ? 'md' : 'json'),\n 'json',\n )\n .option('-o, --out-file <path>', 'Write report to file')\n .option('--full-tree', 'Include full npm ls tree (omit depth=0 default)', false)\n\n if (allowOmitDev) {\n cmd.option('--omit-dev', 'Exclude devDependencies (local only)', false)\n }\n\n return cmd\n}\n\n/**\n * Creates the local command handler\n *\n * @param program - Commander program instance\n * @returns Command instance\n */\nexport function createLocalCommand(program: Command): Command {\n const localCmd = program\n .command('local', { isDefault: true })\n .description(\"Generate a report for the current project's dependencies\")\n\n addCommonOptions(localCmd, { allowOmitDev: true })\n\n localCmd.action(async (opts) => {\n const outputFormat = (opts.outputFormat ?? 'json') as OutputFormat\n const outFile = opts.outFile as string | undefined\n const fullTree = Boolean(opts.fullTree)\n const omitDev = Boolean(opts.omitDev)\n\n // Only set finalOutFile when explicitly provided via --out-file\n const finalOutFile = outFile\n\n const { report, markdownExtras } = await produceReport('local', {\n outputFormat,\n outFile: finalOutFile,\n fullTree,\n omitDev,\n })\n\n await outputReport(report, outputFormat, finalOutFile, markdownExtras)\n })\n\n return localCmd\n}\n\n/**\n * Creates the global command handler\n *\n * @param program - Commander program instance\n * @returns Command instance\n */\nexport function createGlobalCommand(program: Command): Command {\n const globalCmd = program\n .command('global')\n .description('Generate a report of globally installed packages')\n\n addCommonOptions(globalCmd, { allowOmitDev: false })\n\n globalCmd.action(async (opts) => {\n const outputFormat = (opts.outputFormat ?? 'json') as OutputFormat\n const outFile = opts.outFile as string | undefined\n const fullTree = Boolean(opts.fullTree)\n\n // Only set finalOutFile when explicitly provided via --out-file\n const finalOutFile = outFile\n\n const { report, markdownExtras } = await produceReport('global', {\n outputFormat,\n outFile: finalOutFile,\n fullTree,\n })\n\n await outputReport(report, outputFormat, finalOutFile, markdownExtras)\n })\n\n return globalCmd\n}\n\n/**\n * Creates the read command handler\n *\n * @param program - Commander program instance\n * @returns Command instance\n */\nexport function createReadCommand(program: Command): Command {\n const readCmd = program\n .command('read')\n .description(\n 'Read a previously generated report (JSON or Markdown) and either print package names or install them',\n )\n .argument('[report]', 'Path to report file (JSON or Markdown)', 'gex-report.json')\n .option('-r, --report <path>', 'Path to report file (JSON or Markdown)')\n .option('-p, --print', 'Print package names/versions from the report (default)', false)\n .option('-i, --install', 'Install packages from the report', false)\n\n readCmd.action(async (reportArg: string | undefined, opts: any) => {\n const chosen = (opts.report as string | undefined) || reportArg || 'gex-report.json'\n const reportPath = path.resolve(process.cwd(), chosen)\n\n try {\n const parsed = await loadReportFromFile(reportPath)\n\n const doInstall = Boolean(opts.install)\n const doPrint = Boolean(opts.print) || !doInstall\n\n if (doPrint) {\n printFromReport(parsed)\n }\n if (doInstall) {\n await installFromReport(parsed, process.cwd())\n }\n } catch (err: any) {\n const isMd = isMarkdownReportFile(reportPath)\n const hint = isMd\n ? 'Try generating a JSON report with: gex global -f json -o global.json, then: gex read global.json'\n : 'Specify a report path with: gex read <path-to-report.json>'\n console.error(`Failed to read report at ${reportPath}: ${err?.message || err}`)\n console.error(hint)\n process.exitCode = 1\n }\n })\n\n return readCmd\n}\n\n/**\n * Creates and configures the main CLI program\n *\n * @returns Configured Commander program\n */\nexport async function createProgram(): Promise<Command> {\n const program = new Command()\n .name('gex')\n .description('GEX: Dependency auditing and documentation for Node.js (local and global).')\n .version(await getToolVersion())\n\n program.addHelpText('beforeAll', `\\n${ASCII_BANNER}`)\n\n createLocalCommand(program)\n createGlobalCommand(program)\n createReadCommand(program)\n\n return program\n}\n","/**\n * @fileoverview Package installation utilities for CLI\n */\n\nimport type { Report } from '../types.js'\n\n/**\n * Lazily obtain a promisified execFile so tests can mock built-ins reliably.\n */\nasync function getExecFileAsync(): Promise<\n (\n command: string,\n args?: readonly string[] | null,\n options?: any,\n ) => Promise<{ stdout: string; stderr: string }>\n> {\n const { execFile } = await import('node:child_process')\n const { promisify } = await import('node:util')\n return promisify(execFile) as any\n}\n\n/**\n * Installs packages from a report to the local environment\n *\n * @param report - The report containing packages to install\n * @param cwd - Current working directory for installation\n * @throws {Error} If npm installation fails\n */\nexport async function installFromReport(report: Report, cwd: string): Promise<void> {\n const globalPkgs = report.global_packages.map((p) => `${p.name}@${p.version}`).filter(Boolean)\n const localPkgs = report.local_dependencies.map((p) => `${p.name}@${p.version}`).filter(Boolean)\n const devPkgs = report.local_dev_dependencies.map((p) => `${p.name}@${p.version}`).filter(Boolean)\n\n if (globalPkgs.length === 0 && localPkgs.length === 0 && devPkgs.length === 0) {\n console.log('No packages to install from report.')\n return\n }\n\n // Acquire execFileAsync once per run to keep logs grouped, while still mockable in tests\n const execFileAsync = await getExecFileAsync()\n\n if (globalPkgs.length > 0) {\n console.log(`Installing global: ${globalPkgs.join(' ')}`)\n await execFileAsync('npm', ['i', '-g', ...globalPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 })\n }\n\n if (localPkgs.length > 0) {\n console.log(`Installing local deps: ${localPkgs.join(' ')}`)\n await execFileAsync('npm', ['i', ...localPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 })\n }\n\n if (devPkgs.length > 0) {\n console.log(`Installing local devDeps: ${devPkgs.join(' ')}`)\n await execFileAsync('npm', ['i', '-D', ...devPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 })\n }\n}\n\n/**\n * Prints packages from a report to the console\n *\n * @param report - The report to print packages from\n */\nexport function printFromReport(report: Report): void {\n const lines: string[] = []\n\n if (report.global_packages.length > 0) {\n lines.push('Global Packages:')\n for (const p of report.global_packages) {\n lines.push(`- ${p.name}@${p.version}`)\n }\n }\n\n if (report.local_dependencies.length > 0) {\n if (lines.length) lines.push('')\n lines.push('Local Dependencies:')\n for (const p of report.local_dependencies) {\n lines.push(`- ${p.name}@${p.version}`)\n }\n }\n\n if (report.local_dev_dependencies.length > 0) {\n if (lines.length) lines.push('')\n lines.push('Local Dev Dependencies:')\n for (const p of report.local_dev_dependencies) {\n lines.push(`- ${p.name}@${p.version}`)\n }\n }\n\n if (lines.length === 0) {\n lines.push('(no packages found in report)')\n }\n\n console.log(lines.join('\\n'))\n}\n","/**\n * @fileoverview Report output utilities for CLI\n */\n\nimport path from 'node:path'\n\nimport { renderJson } from '../report/json.js'\nimport { renderMarkdown } from '../report/md.js'\nimport type { OutputFormat, Report } from '../types.js'\n\n/**\n * Outputs a report to console or file\n *\n * @param report - The report to output\n * @param format - Output format ('json' or 'md')\n * @param outFile - Optional file path to write to\n * @param markdownExtras - Additional metadata for markdown rendering\n */\nexport async function outputReport(\n report: Report,\n format: OutputFormat,\n outFile?: string,\n markdownExtras?: any,\n): Promise<void> {\n const content =\n format === 'json'\n ? renderJson(report)\n : renderMarkdown({ ...report, ...(markdownExtras || {}) })\n\n if (outFile) {\n const outDir = path.dirname(outFile)\n const { mkdir, writeFile } = await import('node:fs/promises')\n\n await mkdir(outDir, { recursive: true })\n await writeFile(outFile, content, 'utf8')\n\n console.log(`Wrote report to ${outFile}`)\n } else {\n console.log(content)\n }\n}\n","/**\n * @fileoverview JSON report rendering utilities\n */\n\nimport type { Report } from '../types.js'\n\n/**\n * Renders a Report object as formatted JSON string\n *\n * @param report - Report object to render\n * @returns Pretty-printed JSON string with consistent package ordering\n *\n * @example\n * ```typescript\n * import { renderJson } from './report/json.js'\n *\n * const report = {\n * report_version: '1.0',\n * timestamp: new Date().toISOString(),\n * tool_version: '0.3.2',\n * global_packages: [],\n * local_dependencies: [{ name: 'axios', version: '1.6.0', resolved_path: '/path/to/axios' }],\n * local_dev_dependencies: []\n * }\n *\n * const jsonOutput = renderJson(report)\n * console.log(jsonOutput) // Pretty-printed JSON\n * ```\n */\nexport function renderJson(report: Report): string {\n const r: Report = {\n ...report,\n global_packages: [...report.global_packages].sort((a, b) => a.name.localeCompare(b.name)),\n local_dependencies: [...report.local_dependencies].sort((a, b) => a.name.localeCompare(b.name)),\n local_dev_dependencies: [...report.local_dev_dependencies].sort((a, b) =>\n a.name.localeCompare(b.name),\n ),\n }\n return JSON.stringify(r, null, 2)\n}\n","/**\n * @fileoverview Markdown report rendering utilities\n */\n\nimport type { Report } from '../types.js'\n\n/**\n * Creates a markdown table from headers and row data\n *\n * @param headers - Array of table header strings\n * @param rows - Array of row data (each row is array of strings)\n * @returns Formatted markdown table string\n */\nfunction table(headers: string[], rows: string[][]): string {\n const header = `| ${headers.join(' | ')} |`\n const sep = `| ${headers.map(() => '---').join(' | ')} |`\n const body = rows.map((r) => `| ${r.join(' | ')} |`).join('\\n')\n return [header, sep, body].filter(Boolean).join('\\n')\n}\n\n/**\n * Renders a Report object as formatted Markdown\n *\n * @param report - Report object with optional project metadata\n * @returns Formatted Markdown string with tables and sections\n *\n * @example\n * ```typescript\n * import { renderMarkdown } from './report/md.js'\n *\n * const report = {\n * report_version: '1.0',\n * timestamp: new Date().toISOString(),\n * tool_version: '0.3.2',\n * project_name: 'my-project',\n * global_packages: [],\n * local_dependencies: [\n * { name: 'axios', version: '1.6.0', resolved_path: '/path/to/axios' }\n * ],\n * local_dev_dependencies: [],\n * project_description: 'My awesome project'\n * }\n *\n * const markdown = renderMarkdown(report)\n * console.log(markdown) // Formatted markdown with tables\n * ```\n */\nexport function renderMarkdown(\n report: Report & {\n project_description?: string\n project_homepage?: string\n project_bugs?: string\n },\n): string {\n const lines: string[] = []\n lines.push('# GEX Report')\n lines.push('')\n\n if (\n report.project_name ||\n report.project_version ||\n (report as any).project_description ||\n (report as any).project_homepage ||\n (report as any).project_bugs\n ) {\n lines.push('## Project Metadata')\n if (report.project_name) lines.push(`- Name: ${report.project_name}`)\n if (report.project_version) lines.push(`- Version: ${report.project_version}`)\n if ((report as any).project_description)\n lines.push(`- Description: ${(report as any).project_description}`)\n if ((report as any).project_homepage)\n lines.push(`- Homepage: ${(report as any).project_homepage}`)\n if ((report as any).project_bugs) lines.push(`- Bugs: ${(report as any).project_bugs}`)\n lines.push('')\n }\n\n if (report.global_packages.length > 0) {\n lines.push('## Global Packages')\n const rows = report.global_packages.map((p) => [p.name, p.version || '', p.resolved_path || ''])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n if (report.local_dependencies.length > 0) {\n lines.push('## Local Dependencies')\n const rows = report.local_dependencies.map((p) => [\n p.name,\n p.version || '',\n p.resolved_path || '',\n ])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n if (report.local_dev_dependencies.length > 0) {\n lines.push('## Local Dev Dependencies')\n const rows = report.local_dev_dependencies.map((p) => [\n p.name,\n p.version || '',\n p.resolved_path || '',\n ])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n lines.push('---')\n lines.push('_Generated by GEX_')\n\n return lines.join('\\n')\n}\n","/**\n * @fileoverview Report parsing utilities for CLI\n */\n\nimport { readFile } from 'node:fs/promises'\nimport path from 'node:path'\n\nimport type { PackageInfo, Report } from '../types.js'\n\n/**\n * Checks if a file path indicates a markdown report\n */\nexport function isMarkdownReportFile(filePath: string): boolean {\n const ext = path.extname(filePath).toLowerCase()\n return ext === '.md' || ext === '.markdown'\n}\n\n/**\n * Parses a markdown table and extracts package information\n *\n * @param lines - Array of file lines\n * @param startIndex - Index where table starts\n * @returns Array of package information\n */\nfunction parseMarkdownPackagesTable(lines: string[], startIndex: number): PackageInfo[] {\n const rows: PackageInfo[] = []\n if (!lines[startIndex] || !lines[startIndex].trim().startsWith('|')) return rows\n\n let i = startIndex + 2\n while (i < lines.length && lines[i].trim().startsWith('|')) {\n const cols = lines[i]\n .split('|')\n .map((c) => c.trim())\n .filter((_, idx, arr) => !(idx === 0 || idx === arr.length - 1))\n\n const [name = '', version = '', resolved_path = ''] = cols\n if (name) rows.push({ name, version, resolved_path })\n i++\n }\n return rows\n}\n\n/**\n * Parses a markdown report and converts it to a Report object\n *\n * @param md - Markdown content to parse\n * @returns Parsed Report object\n */\nexport function parseMarkdownReport(md: string): Report {\n const lines = md.split(/\\r?\\n/)\n\n const findSection = (title: string) =>\n lines.findIndex((l) => l.trim().toLowerCase() === `## ${title}`.toLowerCase())\n\n const parseSection = (idx: number): PackageInfo[] => {\n if (idx < 0) return []\n\n let i = idx + 1\n while (i < lines.length && !lines[i].trim().startsWith('|')) i++\n return parseMarkdownPackagesTable(lines, i)\n }\n\n const global_packages = parseSection(findSection('Global Packages'))\n const local_dependencies = parseSection(findSection('Local Dependencies'))\n const local_dev_dependencies = parseSection(findSection('Local Dev Dependencies'))\n\n const report: Report = {\n report_version: '1.0',\n timestamp: new Date().toISOString(),\n tool_version: 'unknown',\n global_packages,\n local_dependencies,\n local_dev_dependencies,\n }\n return report\n}\n\n/**\n * Loads and parses a report file (JSON or Markdown)\n *\n * @param reportPath - Path to the report file\n * @returns Parsed Report object\n * @throws {Error} If file cannot be read or parsed\n */\nexport async function loadReportFromFile(reportPath: string): Promise<Report> {\n const raw = await readFile(reportPath, 'utf8')\n\n if (isMarkdownReportFile(reportPath) || raw.startsWith('# GEX Report')) {\n return parseMarkdownReport(raw)\n }\n\n return JSON.parse(raw) as Report\n}\n","/**\n * @fileoverview Report generation utilities for CLI\n */\n\nimport { readFile } from 'node:fs/promises'\nimport path from 'node:path'\n\nimport { npmLs, npmRootGlobal } from '../npm.js'\nimport { buildReportFromNpmTree } from '../transform.js'\nimport type { OutputFormat, Report } from '../types.js'\n\nimport { getToolVersion } from './utils.js'\n\n/**\n * Options for report generation\n */\nexport interface ReportOptions {\n outputFormat: OutputFormat\n outFile?: string\n fullTree?: boolean\n omitDev?: boolean\n cwd?: string\n}\n\n/**\n * Result of report generation including markdown extras\n */\nexport interface ReportResult {\n report: Report\n markdownExtras?: {\n project_description?: string\n project_homepage?: string\n project_bugs?: string\n }\n}\n\n/**\n * Produces a dependency report for local or global context\n *\n * @param ctx - Context for report generation ('local' or 'global')\n * @param options - Report generation options\n * @returns Report and optional markdown extras\n */\nexport async function produceReport(\n ctx: 'local' | 'global',\n options: ReportOptions,\n): Promise<ReportResult> {\n const toolVersion = await getToolVersion()\n const depth0 = !options.fullTree\n const cwd = options.cwd || process.cwd()\n\n const tree = await npmLs({\n global: ctx === 'global',\n omitDev: ctx === 'local' ? Boolean(options.omitDev) : false,\n depth0,\n cwd,\n })\n\n let project_description: string | undefined\n let project_homepage: string | undefined\n let project_bugs: string | undefined\n\n if (ctx === 'local') {\n try {\n const pkgRaw = await readFile(path.join(cwd, 'package.json'), 'utf8')\n const pkg = JSON.parse(pkgRaw)\n project_description = pkg.description\n project_homepage = pkg.homepage\n if (typeof pkg.bugs === 'string') project_bugs = pkg.bugs\n else if (pkg.bugs && typeof pkg.bugs.url === 'string') project_bugs = pkg.bugs.url\n } catch {\n // Ignore errors reading local package.json (e.g., file missing or invalid JSON)\n void 0\n }\n }\n\n const globalRoot = ctx === 'global' ? await npmRootGlobal().catch(() => undefined) : undefined\n\n const report = await buildReportFromNpmTree(tree, {\n context: ctx,\n includeTree: Boolean(options.fullTree),\n omitDev: Boolean(options.omitDev),\n cwd,\n toolVersion,\n globalRoot,\n })\n\n const markdownExtras = { project_description, project_homepage, project_bugs }\n return { report, markdownExtras }\n}\n","/**\n * @fileoverview npm command execution utilities for dependency analysis\n */\n\n/**\n * Lazily obtain a promisified execFile so tests can mock built-ins reliably.\n */\nasync function getExecFileAsync(): Promise<\n (\n command: string,\n args?: readonly string[] | null,\n options?: any,\n ) => Promise<{ stdout: string; stderr: string }>\n> {\n const { execFile } = await import('node:child_process')\n const { promisify } = await import('node:util')\n return promisify(execFile) as any\n}\n\n/**\n * Options for npm ls command execution\n */\nexport type NpmLsOptions = {\n /** Whether to list global packages */\n global?: boolean\n /** Whether to omit devDependencies */\n omitDev?: boolean\n /** Whether to use depth=0 for faster execution */\n depth0?: boolean\n /** Current working directory for command execution */\n cwd?: string\n}\n\n/**\n * Executes npm ls command and returns parsed dependency tree\n *\n * @param options - Configuration options for npm ls command\n * @returns Promise resolving to npm dependency tree object\n * @throws {Error} If npm command fails or output cannot be parsed\n *\n * @example\n * ```typescript\n * import { npmLs } from './npm.js'\n *\n * // Get local dependencies with devDependencies omitted\n * const tree = await npmLs({ omitDev: true, depth0: true })\n *\n * // Get global packages\n * const globalTree = await npmLs({ global: true })\n * ```\n */\nexport async function npmLs(options: NpmLsOptions = {}): Promise<any> {\n const args = ['ls', '--json']\n if (options.global) args.push('--global')\n if (options.omitDev) args.push('--omit=dev')\n if (options.depth0) args.push('--depth=0')\n\n try {\n const execFileAsync = await getExecFileAsync()\n const { stdout } = await execFileAsync('npm', args, {\n cwd: options.cwd,\n maxBuffer: 10 * 1024 * 1024,\n })\n if (stdout && stdout.trim()) return JSON.parse(stdout)\n return {}\n } catch (err: any) {\n const stdout = err?.stdout\n if (typeof stdout === 'string' && stdout.trim()) {\n try {\n return JSON.parse(stdout)\n } catch (parseErr) {\n if (process.env.DEBUG?.includes('gex')) {\n console.warn('npm ls stdout parse failed:', parseErr)\n }\n }\n }\n const stderr = err?.stderr\n const msg = (typeof stderr === 'string' && stderr.trim()) || err?.message || 'npm ls failed'\n throw new Error(`npm ls failed: ${msg}`)\n }\n}\n\n/**\n * Gets the global npm root directory path\n *\n * @returns Promise resolving to the global npm root path\n * @throws {Error} If npm root -g command fails\n *\n * @example\n * ```typescript\n * import { npmRootGlobal } from './npm.js'\n *\n * try {\n * const globalRoot = await npmRootGlobal()\n * console.log('Global npm root:', globalRoot)\n * } catch (error) {\n * console.error('Failed to get global root:', error.message)\n * }\n * ```\n */\nexport async function npmRootGlobal(): Promise<string> {\n try {\n const execFileAsync = await getExecFileAsync()\n const { stdout } = await execFileAsync('npm', ['root', '-g'])\n return stdout.trim()\n } catch (err: any) {\n const stderr = err?.stderr\n const msg =\n (typeof stderr === 'string' && stderr.trim()) || err?.message || 'npm root -g failed'\n throw new Error(`npm root -g failed: ${msg}`)\n }\n}\n","/**\n * @fileoverview Data transformation utilities for converting npm tree data into reports\n */\n\nimport path from 'node:path'\nimport { readFile } from 'node:fs/promises'\n\nimport type { PackageInfo, Report } from './types.js'\n\n/**\n * Options for report generation and normalization\n */\nexport type NormalizeOptions = {\n /** Context for report generation ('local' or 'global') */\n context: 'local' | 'global'\n /** Whether to include the full npm dependency tree */\n includeTree?: boolean\n /** Whether to omit devDependencies (local context only) */\n omitDev?: boolean\n /** Current working directory */\n cwd?: string\n /** Tool version to include in report */\n toolVersion: string\n /** Global npm root directory path */\n globalRoot?: string\n}\n\n/**\n * Converts npm dependency object to array of package entries\n *\n * @param obj - npm dependency object from npm ls output\n * @returns Array of name/node pairs for packages\n */\nfunction toPkgArray(obj: Record<string, any> | undefined | null): { name: string; node: any }[] {\n if (!obj) return []\n return Object.keys(obj)\n .map((name) => ({ name, node: obj[name] }))\n .filter((p) => p && p.node)\n}\n\n/**\n * Builds a GEX report from npm ls tree output\n *\n * @param tree - Raw npm ls command output\n * @param opts - Report generation options\n * @returns Promise resolving to a formatted Report object\n *\n * @example\n * ```typescript\n * import { buildReportFromNpmTree } from './transform.js'\n * import { npmLs } from './npm.js'\n *\n * const tree = await npmLs({ depth0: true })\n * const report = await buildReportFromNpmTree(tree, {\n * context: 'local',\n * toolVersion: '0.3.2',\n * cwd: process.cwd()\n * })\n *\n * console.log(`Found ${report.local_dependencies.length} dependencies`)\n * ```\n */\nexport async function buildReportFromNpmTree(tree: any, opts: NormalizeOptions): Promise<Report> {\n const timestamp = new Date().toISOString()\n const report: Report = {\n report_version: '1.0',\n timestamp,\n tool_version: opts.toolVersion,\n global_packages: [],\n local_dependencies: [],\n local_dev_dependencies: [],\n }\n\n if (opts.context === 'local') {\n let pkgMeta: any = null\n try {\n const pkgJsonPath = path.join(opts.cwd || process.cwd(), 'package.json')\n const raw = await readFile(pkgJsonPath, 'utf8')\n pkgMeta = JSON.parse(raw)\n } catch {\n // Ignore errors reading/parsing package.json; fall back to undefined metadata\n void 0\n }\n if (pkgMeta?.name) report.project_name = pkgMeta.name\n if (pkgMeta?.version) report.project_version = pkgMeta.version\n\n const depsObj = tree?.dependencies as Record<string, any> | undefined\n const items = toPkgArray(depsObj)\n const devKeys = new Set(Object.keys((pkgMeta?.devDependencies as Record<string, string>) || {}))\n\n for (const { name, node } of items) {\n const version = (node && node.version) || ''\n const resolvedPath =\n (node && node.path) || path.join(opts.cwd || process.cwd(), 'node_modules', name)\n const pkg: PackageInfo = { name, version, resolved_path: resolvedPath }\n if (devKeys.has(name)) {\n report.local_dev_dependencies.push(pkg)\n } else {\n report.local_dependencies.push(pkg)\n }\n }\n\n report.local_dependencies.sort((a, b) => a.name.localeCompare(b.name))\n report.local_dev_dependencies.sort((a, b) => a.name.localeCompare(b.name))\n } else if (opts.context === 'global') {\n const depsObj = tree?.dependencies as Record<string, any> | undefined\n const items = toPkgArray(depsObj)\n\n for (const { name, node } of items) {\n const version = (node && node.version) || ''\n const resolvedPath = (node && node.path) || path.join(opts.globalRoot || '', name)\n const pkg: PackageInfo = { name, version, resolved_path: resolvedPath }\n report.global_packages.push(pkg)\n }\n\n report.global_packages.sort((a, b) => a.name.localeCompare(b.name))\n }\n\n if (opts.includeTree) {\n report.tree = tree\n }\n\n return report\n}\n","/**\n * @fileoverview CLI utility functions for version handling and path resolution\n */\n\nimport { readFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\n/**\n * Gets the path to package.json for version resolution\n */\nexport function getPkgJsonPath(): string {\n try {\n const __filename = fileURLToPath((import.meta as any).url)\n const __dirnameLocal = path.dirname(__filename)\n return path.resolve(__dirnameLocal, '..', '..', 'package.json')\n } catch {\n const dir = typeof __dirname !== 'undefined' ? __dirname : process.cwd()\n return path.resolve(dir, '..', 'package.json')\n }\n}\n\n/**\n * Gets the current tool version from package.json\n */\nexport async function getToolVersion(): Promise<string> {\n try {\n const pkgPath = getPkgJsonPath()\n const raw = await readFile(pkgPath, 'utf8')\n const pkg = JSON.parse(raw)\n return pkg.version || '0.0.0'\n } catch {\n return '0.0.0'\n }\n}\n\n/**\n * ASCII banner for the CLI\n */\nexport const ASCII_BANNER = String.raw`\n ________ __\n / _____/ ____ _____/ |_ ____ ____\n/ \\ ___ / _ \\ / _ \\ __\\/ __ \\ / \\\n\\ \\_\\ ( <_> | <_> ) | \\ ___/| | \\\n \\______ /\\____/ \\____/|__| \\___ >___| /\n \\/ \\/ \\/\n GEX\n`\n"],"mappings":"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","names":["import_node_path","path","import_node_path","path","import_promises","import_node_path","getExecFileAsync","import_node_path","import_promises","path","import_promises","import_node_path","path","path","path","import_meta"]}
package/dist/cli.mjs CHANGED
@@ -401,10 +401,7 @@ function createLocalCommand(program) {
401
401
  const outFile = opts.outFile;
402
402
  const fullTree = Boolean(opts.fullTree);
403
403
  const omitDev = Boolean(opts.omitDev);
404
- let finalOutFile = outFile;
405
- if (!outFile && opts.outputFormat && typeof opts.outputFormat === "string") {
406
- finalOutFile = `gex-report.${outputFormat}`;
407
- }
404
+ const finalOutFile = outFile;
408
405
  const { report, markdownExtras } = await produceReport("local", {
409
406
  outputFormat,
410
407
  outFile: finalOutFile,
@@ -422,10 +419,7 @@ function createGlobalCommand(program) {
422
419
  const outputFormat = opts.outputFormat ?? "json";
423
420
  const outFile = opts.outFile;
424
421
  const fullTree = Boolean(opts.fullTree);
425
- let finalOutFile = outFile;
426
- if (!outFile && opts.outputFormat && typeof opts.outputFormat === "string") {
427
- finalOutFile = `gex-report.${outputFormat}`;
428
- }
422
+ const finalOutFile = outFile;
429
423
  const { report, markdownExtras } = await produceReport("global", {
430
424
  outputFormat,
431
425
  outFile: finalOutFile,
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/commands.ts","../src/cli/install.ts","../src/cli/output.ts","../src/report/json.ts","../src/report/md.ts","../src/cli/parser.ts","../src/cli/report.ts","../src/npm.ts","../src/transform.ts","../src/cli/utils.ts","../src/cli.ts"],"sourcesContent":["/**\n * @fileoverview CLI command definitions and handlers\n */\n\nimport path from 'node:path'\n\nimport { Command } from 'commander'\n\nimport type { OutputFormat } from '../types.js'\n\nimport { installFromReport, printFromReport } from './install.js'\nimport { outputReport } from './output.js'\nimport { isMarkdownReportFile, loadReportFromFile } from './parser.js'\nimport { produceReport } from './report.js'\nimport { ASCII_BANNER, getToolVersion } from './utils.js'\n\n/**\n * Adds common options to a command\n *\n * @param cmd - Command to add options to\n * @param options - Configuration for which options to add\n * @returns Modified command\n */\nfunction addCommonOptions(cmd: Command, { allowOmitDev }: { allowOmitDev: boolean }): Command {\n cmd\n .option(\n '-f, --output-format <format>',\n 'Output format: md or json',\n (val) => (val === 'md' ? 'md' : 'json'),\n 'json',\n )\n .option('-o, --out-file <path>', 'Write report to file')\n .option('--full-tree', 'Include full npm ls tree (omit depth=0 default)', false)\n\n if (allowOmitDev) {\n cmd.option('--omit-dev', 'Exclude devDependencies (local only)', false)\n }\n\n return cmd\n}\n\n/**\n * Creates the local command handler\n *\n * @param program - Commander program instance\n * @returns Command instance\n */\nexport function createLocalCommand(program: Command): Command {\n const localCmd = program\n .command('local', { isDefault: true })\n .description(\"Generate a report for the current project's dependencies\")\n\n addCommonOptions(localCmd, { allowOmitDev: true })\n\n localCmd.action(async (opts) => {\n const outputFormat = (opts.outputFormat ?? 'json') as OutputFormat\n const outFile = opts.outFile as string | undefined\n const fullTree = Boolean(opts.fullTree)\n const omitDev = Boolean(opts.omitDev)\n\n let finalOutFile = outFile\n if (!outFile && opts.outputFormat && typeof opts.outputFormat === 'string') {\n finalOutFile = `gex-report.${outputFormat}`\n }\n\n const { report, markdownExtras } = await produceReport('local', {\n outputFormat,\n outFile: finalOutFile,\n fullTree,\n omitDev,\n })\n\n await outputReport(report, outputFormat, finalOutFile, markdownExtras)\n })\n\n return localCmd\n}\n\n/**\n * Creates the global command handler\n *\n * @param program - Commander program instance\n * @returns Command instance\n */\nexport function createGlobalCommand(program: Command): Command {\n const globalCmd = program\n .command('global')\n .description('Generate a report of globally installed packages')\n\n addCommonOptions(globalCmd, { allowOmitDev: false })\n\n globalCmd.action(async (opts) => {\n const outputFormat = (opts.outputFormat ?? 'json') as OutputFormat\n const outFile = opts.outFile as string | undefined\n const fullTree = Boolean(opts.fullTree)\n\n let finalOutFile = outFile\n if (!outFile && opts.outputFormat && typeof opts.outputFormat === 'string') {\n finalOutFile = `gex-report.${outputFormat}`\n }\n\n const { report, markdownExtras } = await produceReport('global', {\n outputFormat,\n outFile: finalOutFile,\n fullTree,\n })\n\n await outputReport(report, outputFormat, finalOutFile, markdownExtras)\n })\n\n return globalCmd\n}\n\n/**\n * Creates the read command handler\n *\n * @param program - Commander program instance\n * @returns Command instance\n */\nexport function createReadCommand(program: Command): Command {\n const readCmd = program\n .command('read')\n .description(\n 'Read a previously generated report (JSON or Markdown) and either print package names or install them',\n )\n .argument('[report]', 'Path to report file (JSON or Markdown)', 'gex-report.json')\n .option('-r, --report <path>', 'Path to report file (JSON or Markdown)')\n .option('-p, --print', 'Print package names/versions from the report (default)', false)\n .option('-i, --install', 'Install packages from the report', false)\n\n readCmd.action(async (reportArg: string | undefined, opts: any) => {\n const chosen = (opts.report as string | undefined) || reportArg || 'gex-report.json'\n const reportPath = path.resolve(process.cwd(), chosen)\n\n try {\n const parsed = await loadReportFromFile(reportPath)\n\n const doInstall = Boolean(opts.install)\n const doPrint = Boolean(opts.print) || !doInstall\n\n if (doPrint) {\n printFromReport(parsed)\n }\n if (doInstall) {\n await installFromReport(parsed, process.cwd())\n }\n } catch (err: any) {\n const isMd = isMarkdownReportFile(reportPath)\n const hint = isMd\n ? 'Try generating a JSON report with: gex global -f json -o global.json, then: gex read global.json'\n : 'Specify a report path with: gex read <path-to-report.json>'\n console.error(`Failed to read report at ${reportPath}: ${err?.message || err}`)\n console.error(hint)\n process.exitCode = 1\n }\n })\n\n return readCmd\n}\n\n/**\n * Creates and configures the main CLI program\n *\n * @returns Configured Commander program\n */\nexport async function createProgram(): Promise<Command> {\n const program = new Command()\n .name('gex')\n .description('GEX: Dependency auditing and documentation for Node.js (local and global).')\n .version(await getToolVersion())\n\n program.addHelpText('beforeAll', `\\n${ASCII_BANNER}`)\n\n createLocalCommand(program)\n createGlobalCommand(program)\n createReadCommand(program)\n\n return program\n}\n","/**\n * @fileoverview Package installation utilities for CLI\n */\n\nimport type { Report } from '../types.js'\n\n/**\n * Lazily obtain a promisified execFile so tests can mock built-ins reliably.\n */\nasync function getExecFileAsync(): Promise<\n (\n command: string,\n args?: readonly string[] | null,\n options?: any,\n ) => Promise<{ stdout: string; stderr: string }>\n> {\n const { execFile } = await import('node:child_process')\n const { promisify } = await import('node:util')\n return promisify(execFile) as any\n}\n\n/**\n * Installs packages from a report to the local environment\n *\n * @param report - The report containing packages to install\n * @param cwd - Current working directory for installation\n * @throws {Error} If npm installation fails\n */\nexport async function installFromReport(report: Report, cwd: string): Promise<void> {\n const globalPkgs = report.global_packages.map((p) => `${p.name}@${p.version}`).filter(Boolean)\n const localPkgs = report.local_dependencies.map((p) => `${p.name}@${p.version}`).filter(Boolean)\n const devPkgs = report.local_dev_dependencies.map((p) => `${p.name}@${p.version}`).filter(Boolean)\n\n if (globalPkgs.length === 0 && localPkgs.length === 0 && devPkgs.length === 0) {\n console.log('No packages to install from report.')\n return\n }\n\n // Acquire execFileAsync once per run to keep logs grouped, while still mockable in tests\n const execFileAsync = await getExecFileAsync()\n\n if (globalPkgs.length > 0) {\n console.log(`Installing global: ${globalPkgs.join(' ')}`)\n await execFileAsync('npm', ['i', '-g', ...globalPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 })\n }\n\n if (localPkgs.length > 0) {\n console.log(`Installing local deps: ${localPkgs.join(' ')}`)\n await execFileAsync('npm', ['i', ...localPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 })\n }\n\n if (devPkgs.length > 0) {\n console.log(`Installing local devDeps: ${devPkgs.join(' ')}`)\n await execFileAsync('npm', ['i', '-D', ...devPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 })\n }\n}\n\n/**\n * Prints packages from a report to the console\n *\n * @param report - The report to print packages from\n */\nexport function printFromReport(report: Report): void {\n const lines: string[] = []\n\n if (report.global_packages.length > 0) {\n lines.push('Global Packages:')\n for (const p of report.global_packages) {\n lines.push(`- ${p.name}@${p.version}`)\n }\n }\n\n if (report.local_dependencies.length > 0) {\n if (lines.length) lines.push('')\n lines.push('Local Dependencies:')\n for (const p of report.local_dependencies) {\n lines.push(`- ${p.name}@${p.version}`)\n }\n }\n\n if (report.local_dev_dependencies.length > 0) {\n if (lines.length) lines.push('')\n lines.push('Local Dev Dependencies:')\n for (const p of report.local_dev_dependencies) {\n lines.push(`- ${p.name}@${p.version}`)\n }\n }\n\n if (lines.length === 0) {\n lines.push('(no packages found in report)')\n }\n\n console.log(lines.join('\\n'))\n}\n","/**\n * @fileoverview Report output utilities for CLI\n */\n\nimport path from 'node:path'\n\nimport { renderJson } from '../report/json.js'\nimport { renderMarkdown } from '../report/md.js'\nimport type { OutputFormat, Report } from '../types.js'\n\n/**\n * Outputs a report to console or file\n *\n * @param report - The report to output\n * @param format - Output format ('json' or 'md')\n * @param outFile - Optional file path to write to\n * @param markdownExtras - Additional metadata for markdown rendering\n */\nexport async function outputReport(\n report: Report,\n format: OutputFormat,\n outFile?: string,\n markdownExtras?: any,\n): Promise<void> {\n const content =\n format === 'json'\n ? renderJson(report)\n : renderMarkdown({ ...report, ...(markdownExtras || {}) })\n\n if (outFile) {\n const outDir = path.dirname(outFile)\n const { mkdir, writeFile } = await import('node:fs/promises')\n\n await mkdir(outDir, { recursive: true })\n await writeFile(outFile, content, 'utf8')\n\n console.log(`Wrote report to ${outFile}`)\n } else {\n console.log(content)\n }\n}\n","/**\n * @fileoverview JSON report rendering utilities\n */\n\nimport type { Report } from '../types.js'\n\n/**\n * Renders a Report object as formatted JSON string\n *\n * @param report - Report object to render\n * @returns Pretty-printed JSON string with consistent package ordering\n *\n * @example\n * ```typescript\n * import { renderJson } from './report/json.js'\n *\n * const report = {\n * report_version: '1.0',\n * timestamp: new Date().toISOString(),\n * tool_version: '0.3.2',\n * global_packages: [],\n * local_dependencies: [{ name: 'axios', version: '1.6.0', resolved_path: '/path/to/axios' }],\n * local_dev_dependencies: []\n * }\n *\n * const jsonOutput = renderJson(report)\n * console.log(jsonOutput) // Pretty-printed JSON\n * ```\n */\nexport function renderJson(report: Report): string {\n const r: Report = {\n ...report,\n global_packages: [...report.global_packages].sort((a, b) => a.name.localeCompare(b.name)),\n local_dependencies: [...report.local_dependencies].sort((a, b) => a.name.localeCompare(b.name)),\n local_dev_dependencies: [...report.local_dev_dependencies].sort((a, b) =>\n a.name.localeCompare(b.name),\n ),\n }\n return JSON.stringify(r, null, 2)\n}\n","/**\n * @fileoverview Markdown report rendering utilities\n */\n\nimport type { Report } from '../types.js'\n\n/**\n * Creates a markdown table from headers and row data\n *\n * @param headers - Array of table header strings\n * @param rows - Array of row data (each row is array of strings)\n * @returns Formatted markdown table string\n */\nfunction table(headers: string[], rows: string[][]): string {\n const header = `| ${headers.join(' | ')} |`\n const sep = `| ${headers.map(() => '---').join(' | ')} |`\n const body = rows.map((r) => `| ${r.join(' | ')} |`).join('\\n')\n return [header, sep, body].filter(Boolean).join('\\n')\n}\n\n/**\n * Renders a Report object as formatted Markdown\n *\n * @param report - Report object with optional project metadata\n * @returns Formatted Markdown string with tables and sections\n *\n * @example\n * ```typescript\n * import { renderMarkdown } from './report/md.js'\n *\n * const report = {\n * report_version: '1.0',\n * timestamp: new Date().toISOString(),\n * tool_version: '0.3.2',\n * project_name: 'my-project',\n * global_packages: [],\n * local_dependencies: [\n * { name: 'axios', version: '1.6.0', resolved_path: '/path/to/axios' }\n * ],\n * local_dev_dependencies: [],\n * project_description: 'My awesome project'\n * }\n *\n * const markdown = renderMarkdown(report)\n * console.log(markdown) // Formatted markdown with tables\n * ```\n */\nexport function renderMarkdown(\n report: Report & {\n project_description?: string\n project_homepage?: string\n project_bugs?: string\n },\n): string {\n const lines: string[] = []\n lines.push('# GEX Report')\n lines.push('')\n\n if (\n report.project_name ||\n report.project_version ||\n (report as any).project_description ||\n (report as any).project_homepage ||\n (report as any).project_bugs\n ) {\n lines.push('## Project Metadata')\n if (report.project_name) lines.push(`- Name: ${report.project_name}`)\n if (report.project_version) lines.push(`- Version: ${report.project_version}`)\n if ((report as any).project_description)\n lines.push(`- Description: ${(report as any).project_description}`)\n if ((report as any).project_homepage)\n lines.push(`- Homepage: ${(report as any).project_homepage}`)\n if ((report as any).project_bugs) lines.push(`- Bugs: ${(report as any).project_bugs}`)\n lines.push('')\n }\n\n if (report.global_packages.length > 0) {\n lines.push('## Global Packages')\n const rows = report.global_packages.map((p) => [p.name, p.version || '', p.resolved_path || ''])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n if (report.local_dependencies.length > 0) {\n lines.push('## Local Dependencies')\n const rows = report.local_dependencies.map((p) => [\n p.name,\n p.version || '',\n p.resolved_path || '',\n ])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n if (report.local_dev_dependencies.length > 0) {\n lines.push('## Local Dev Dependencies')\n const rows = report.local_dev_dependencies.map((p) => [\n p.name,\n p.version || '',\n p.resolved_path || '',\n ])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n lines.push('---')\n lines.push('_Generated by GEX_')\n\n return lines.join('\\n')\n}\n","/**\n * @fileoverview Report parsing utilities for CLI\n */\n\nimport { readFile } from 'node:fs/promises'\nimport path from 'node:path'\n\nimport type { PackageInfo, Report } from '../types.js'\n\n/**\n * Checks if a file path indicates a markdown report\n */\nexport function isMarkdownReportFile(filePath: string): boolean {\n const ext = path.extname(filePath).toLowerCase()\n return ext === '.md' || ext === '.markdown'\n}\n\n/**\n * Parses a markdown table and extracts package information\n *\n * @param lines - Array of file lines\n * @param startIndex - Index where table starts\n * @returns Array of package information\n */\nfunction parseMarkdownPackagesTable(lines: string[], startIndex: number): PackageInfo[] {\n const rows: PackageInfo[] = []\n if (!lines[startIndex] || !lines[startIndex].trim().startsWith('|')) return rows\n\n let i = startIndex + 2\n while (i < lines.length && lines[i].trim().startsWith('|')) {\n const cols = lines[i]\n .split('|')\n .map((c) => c.trim())\n .filter((_, idx, arr) => !(idx === 0 || idx === arr.length - 1))\n\n const [name = '', version = '', resolved_path = ''] = cols\n if (name) rows.push({ name, version, resolved_path })\n i++\n }\n return rows\n}\n\n/**\n * Parses a markdown report and converts it to a Report object\n *\n * @param md - Markdown content to parse\n * @returns Parsed Report object\n */\nexport function parseMarkdownReport(md: string): Report {\n const lines = md.split(/\\r?\\n/)\n\n const findSection = (title: string) =>\n lines.findIndex((l) => l.trim().toLowerCase() === `## ${title}`.toLowerCase())\n\n const parseSection = (idx: number): PackageInfo[] => {\n if (idx < 0) return []\n\n let i = idx + 1\n while (i < lines.length && !lines[i].trim().startsWith('|')) i++\n return parseMarkdownPackagesTable(lines, i)\n }\n\n const global_packages = parseSection(findSection('Global Packages'))\n const local_dependencies = parseSection(findSection('Local Dependencies'))\n const local_dev_dependencies = parseSection(findSection('Local Dev Dependencies'))\n\n const report: Report = {\n report_version: '1.0',\n timestamp: new Date().toISOString(),\n tool_version: 'unknown',\n global_packages,\n local_dependencies,\n local_dev_dependencies,\n }\n return report\n}\n\n/**\n * Loads and parses a report file (JSON or Markdown)\n *\n * @param reportPath - Path to the report file\n * @returns Parsed Report object\n * @throws {Error} If file cannot be read or parsed\n */\nexport async function loadReportFromFile(reportPath: string): Promise<Report> {\n const raw = await readFile(reportPath, 'utf8')\n\n if (isMarkdownReportFile(reportPath) || raw.startsWith('# GEX Report')) {\n return parseMarkdownReport(raw)\n }\n\n return JSON.parse(raw) as Report\n}\n","/**\n * @fileoverview Report generation utilities for CLI\n */\n\nimport { readFile } from 'node:fs/promises'\nimport path from 'node:path'\n\nimport { npmLs, npmRootGlobal } from '../npm.js'\nimport { buildReportFromNpmTree } from '../transform.js'\nimport type { OutputFormat, Report } from '../types.js'\n\nimport { getToolVersion } from './utils.js'\n\n/**\n * Options for report generation\n */\nexport interface ReportOptions {\n outputFormat: OutputFormat\n outFile?: string\n fullTree?: boolean\n omitDev?: boolean\n cwd?: string\n}\n\n/**\n * Result of report generation including markdown extras\n */\nexport interface ReportResult {\n report: Report\n markdownExtras?: {\n project_description?: string\n project_homepage?: string\n project_bugs?: string\n }\n}\n\n/**\n * Produces a dependency report for local or global context\n *\n * @param ctx - Context for report generation ('local' or 'global')\n * @param options - Report generation options\n * @returns Report and optional markdown extras\n */\nexport async function produceReport(\n ctx: 'local' | 'global',\n options: ReportOptions,\n): Promise<ReportResult> {\n const toolVersion = await getToolVersion()\n const depth0 = !options.fullTree\n const cwd = options.cwd || process.cwd()\n\n const tree = await npmLs({\n global: ctx === 'global',\n omitDev: ctx === 'local' ? Boolean(options.omitDev) : false,\n depth0,\n cwd,\n })\n\n let project_description: string | undefined\n let project_homepage: string | undefined\n let project_bugs: string | undefined\n\n if (ctx === 'local') {\n try {\n const pkgRaw = await readFile(path.join(cwd, 'package.json'), 'utf8')\n const pkg = JSON.parse(pkgRaw)\n project_description = pkg.description\n project_homepage = pkg.homepage\n if (typeof pkg.bugs === 'string') project_bugs = pkg.bugs\n else if (pkg.bugs && typeof pkg.bugs.url === 'string') project_bugs = pkg.bugs.url\n } catch {\n // Ignore errors reading local package.json (e.g., file missing or invalid JSON)\n void 0\n }\n }\n\n const globalRoot = ctx === 'global' ? await npmRootGlobal().catch(() => undefined) : undefined\n\n const report = await buildReportFromNpmTree(tree, {\n context: ctx,\n includeTree: Boolean(options.fullTree),\n omitDev: Boolean(options.omitDev),\n cwd,\n toolVersion,\n globalRoot,\n })\n\n const markdownExtras = { project_description, project_homepage, project_bugs }\n return { report, markdownExtras }\n}\n","/**\n * @fileoverview npm command execution utilities for dependency analysis\n */\n\n/**\n * Lazily obtain a promisified execFile so tests can mock built-ins reliably.\n */\nasync function getExecFileAsync(): Promise<\n (\n command: string,\n args?: readonly string[] | null,\n options?: any,\n ) => Promise<{ stdout: string; stderr: string }>\n> {\n const { execFile } = await import('node:child_process')\n const { promisify } = await import('node:util')\n return promisify(execFile) as any\n}\n\n/**\n * Options for npm ls command execution\n */\nexport type NpmLsOptions = {\n /** Whether to list global packages */\n global?: boolean\n /** Whether to omit devDependencies */\n omitDev?: boolean\n /** Whether to use depth=0 for faster execution */\n depth0?: boolean\n /** Current working directory for command execution */\n cwd?: string\n}\n\n/**\n * Executes npm ls command and returns parsed dependency tree\n *\n * @param options - Configuration options for npm ls command\n * @returns Promise resolving to npm dependency tree object\n * @throws {Error} If npm command fails or output cannot be parsed\n *\n * @example\n * ```typescript\n * import { npmLs } from './npm.js'\n *\n * // Get local dependencies with devDependencies omitted\n * const tree = await npmLs({ omitDev: true, depth0: true })\n *\n * // Get global packages\n * const globalTree = await npmLs({ global: true })\n * ```\n */\nexport async function npmLs(options: NpmLsOptions = {}): Promise<any> {\n const args = ['ls', '--json']\n if (options.global) args.push('--global')\n if (options.omitDev) args.push('--omit=dev')\n if (options.depth0) args.push('--depth=0')\n\n try {\n const execFileAsync = await getExecFileAsync()\n const { stdout } = await execFileAsync('npm', args, {\n cwd: options.cwd,\n maxBuffer: 10 * 1024 * 1024,\n })\n if (stdout && stdout.trim()) return JSON.parse(stdout)\n return {}\n } catch (err: any) {\n const stdout = err?.stdout\n if (typeof stdout === 'string' && stdout.trim()) {\n try {\n return JSON.parse(stdout)\n } catch (parseErr) {\n if (process.env.DEBUG?.includes('gex')) {\n console.warn('npm ls stdout parse failed:', parseErr)\n }\n }\n }\n const stderr = err?.stderr\n const msg = (typeof stderr === 'string' && stderr.trim()) || err?.message || 'npm ls failed'\n throw new Error(`npm ls failed: ${msg}`)\n }\n}\n\n/**\n * Gets the global npm root directory path\n *\n * @returns Promise resolving to the global npm root path\n * @throws {Error} If npm root -g command fails\n *\n * @example\n * ```typescript\n * import { npmRootGlobal } from './npm.js'\n *\n * try {\n * const globalRoot = await npmRootGlobal()\n * console.log('Global npm root:', globalRoot)\n * } catch (error) {\n * console.error('Failed to get global root:', error.message)\n * }\n * ```\n */\nexport async function npmRootGlobal(): Promise<string> {\n try {\n const execFileAsync = await getExecFileAsync()\n const { stdout } = await execFileAsync('npm', ['root', '-g'])\n return stdout.trim()\n } catch (err: any) {\n const stderr = err?.stderr\n const msg =\n (typeof stderr === 'string' && stderr.trim()) || err?.message || 'npm root -g failed'\n throw new Error(`npm root -g failed: ${msg}`)\n }\n}\n","/**\n * @fileoverview Data transformation utilities for converting npm tree data into reports\n */\n\nimport path from 'node:path'\nimport { readFile } from 'node:fs/promises'\n\nimport type { PackageInfo, Report } from './types.js'\n\n/**\n * Options for report generation and normalization\n */\nexport type NormalizeOptions = {\n /** Context for report generation ('local' or 'global') */\n context: 'local' | 'global'\n /** Whether to include the full npm dependency tree */\n includeTree?: boolean\n /** Whether to omit devDependencies (local context only) */\n omitDev?: boolean\n /** Current working directory */\n cwd?: string\n /** Tool version to include in report */\n toolVersion: string\n /** Global npm root directory path */\n globalRoot?: string\n}\n\n/**\n * Converts npm dependency object to array of package entries\n *\n * @param obj - npm dependency object from npm ls output\n * @returns Array of name/node pairs for packages\n */\nfunction toPkgArray(obj: Record<string, any> | undefined | null): { name: string; node: any }[] {\n if (!obj) return []\n return Object.keys(obj)\n .map((name) => ({ name, node: obj[name] }))\n .filter((p) => p && p.node)\n}\n\n/**\n * Builds a GEX report from npm ls tree output\n *\n * @param tree - Raw npm ls command output\n * @param opts - Report generation options\n * @returns Promise resolving to a formatted Report object\n *\n * @example\n * ```typescript\n * import { buildReportFromNpmTree } from './transform.js'\n * import { npmLs } from './npm.js'\n *\n * const tree = await npmLs({ depth0: true })\n * const report = await buildReportFromNpmTree(tree, {\n * context: 'local',\n * toolVersion: '0.3.2',\n * cwd: process.cwd()\n * })\n *\n * console.log(`Found ${report.local_dependencies.length} dependencies`)\n * ```\n */\nexport async function buildReportFromNpmTree(tree: any, opts: NormalizeOptions): Promise<Report> {\n const timestamp = new Date().toISOString()\n const report: Report = {\n report_version: '1.0',\n timestamp,\n tool_version: opts.toolVersion,\n global_packages: [],\n local_dependencies: [],\n local_dev_dependencies: [],\n }\n\n if (opts.context === 'local') {\n let pkgMeta: any = null\n try {\n const pkgJsonPath = path.join(opts.cwd || process.cwd(), 'package.json')\n const raw = await readFile(pkgJsonPath, 'utf8')\n pkgMeta = JSON.parse(raw)\n } catch {\n // Ignore errors reading/parsing package.json; fall back to undefined metadata\n void 0\n }\n if (pkgMeta?.name) report.project_name = pkgMeta.name\n if (pkgMeta?.version) report.project_version = pkgMeta.version\n\n const depsObj = tree?.dependencies as Record<string, any> | undefined\n const items = toPkgArray(depsObj)\n const devKeys = new Set(Object.keys((pkgMeta?.devDependencies as Record<string, string>) || {}))\n\n for (const { name, node } of items) {\n const version = (node && node.version) || ''\n const resolvedPath =\n (node && node.path) || path.join(opts.cwd || process.cwd(), 'node_modules', name)\n const pkg: PackageInfo = { name, version, resolved_path: resolvedPath }\n if (devKeys.has(name)) {\n report.local_dev_dependencies.push(pkg)\n } else {\n report.local_dependencies.push(pkg)\n }\n }\n\n report.local_dependencies.sort((a, b) => a.name.localeCompare(b.name))\n report.local_dev_dependencies.sort((a, b) => a.name.localeCompare(b.name))\n } else if (opts.context === 'global') {\n const depsObj = tree?.dependencies as Record<string, any> | undefined\n const items = toPkgArray(depsObj)\n\n for (const { name, node } of items) {\n const version = (node && node.version) || ''\n const resolvedPath = (node && node.path) || path.join(opts.globalRoot || '', name)\n const pkg: PackageInfo = { name, version, resolved_path: resolvedPath }\n report.global_packages.push(pkg)\n }\n\n report.global_packages.sort((a, b) => a.name.localeCompare(b.name))\n }\n\n if (opts.includeTree) {\n report.tree = tree\n }\n\n return report\n}\n","/**\n * @fileoverview CLI utility functions for version handling and path resolution\n */\n\nimport { readFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\n/**\n * Gets the path to package.json for version resolution\n */\nexport function getPkgJsonPath(): string {\n try {\n const __filename = fileURLToPath((import.meta as any).url)\n const __dirnameLocal = path.dirname(__filename)\n return path.resolve(__dirnameLocal, '..', '..', 'package.json')\n } catch {\n const dir = typeof __dirname !== 'undefined' ? __dirname : process.cwd()\n return path.resolve(dir, '..', 'package.json')\n }\n}\n\n/**\n * Gets the current tool version from package.json\n */\nexport async function getToolVersion(): Promise<string> {\n try {\n const pkgPath = getPkgJsonPath()\n const raw = await readFile(pkgPath, 'utf8')\n const pkg = JSON.parse(raw)\n return pkg.version || '0.0.0'\n } catch {\n return '0.0.0'\n }\n}\n\n/**\n * ASCII banner for the CLI\n */\nexport const ASCII_BANNER = String.raw`\n ________ __\n / _____/ ____ _____/ |_ ____ ____\n/ \\ ___ / _ \\ / _ \\ __\\/ __ \\ / \\\n\\ \\_\\ ( <_> | <_> ) | \\ ___/| | \\\n \\______ /\\____/ \\____/|__| \\___ >___| /\n \\/ \\/ \\/\n GEX\n`\n","/**\n * @fileoverview Main CLI entry point for GEX dependency auditing tool\n */\n\nimport { createProgram } from './cli/commands.js'\n\n/**\n * Main CLI runner function\n *\n * @param argv - Command line arguments (defaults to process.argv)\n */\nexport async function run(argv = process.argv): Promise<void> {\n const program = await createProgram()\n await program.parseAsync(argv)\n}\n\nconst isMainModule = (() => {\n try {\n if (typeof require !== 'undefined' && typeof module !== 'undefined') {\n return (require as any).main === module\n }\n\n if (typeof import.meta !== 'undefined') {\n return import.meta.url === `file://${process.argv[1]}`\n }\n return false\n } catch {\n return false\n }\n})()\n\nif (isMainModule) {\n run().catch((error) => {\n console.error('CLI error:', error)\n process.exitCode = 1\n })\n}\n"],"mappings":";;;;;;;;;AAIA,OAAOA,WAAU;AAEjB,SAAS,eAAe;;;ACGxB,eAAe,mBAMb;AACA,QAAM,EAAE,SAAS,IAAI,MAAM,OAAO,eAAoB;AACtD,QAAM,EAAE,UAAU,IAAI,MAAM,OAAO,MAAW;AAC9C,SAAO,UAAU,QAAQ;AAC3B;AASA,eAAsB,kBAAkB,QAAgB,KAA4B;AAClF,QAAM,aAAa,OAAO,gBAAgB,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,IAAI,EAAE,OAAO,EAAE,EAAE,OAAO,OAAO;AAC7F,QAAM,YAAY,OAAO,mBAAmB,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,IAAI,EAAE,OAAO,EAAE,EAAE,OAAO,OAAO;AAC/F,QAAM,UAAU,OAAO,uBAAuB,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,IAAI,EAAE,OAAO,EAAE,EAAE,OAAO,OAAO;AAEjG,MAAI,WAAW,WAAW,KAAK,UAAU,WAAW,KAAK,QAAQ,WAAW,GAAG;AAC7E,YAAQ,IAAI,qCAAqC;AACjD;AAAA,EACF;AAGA,QAAM,gBAAgB,MAAM,iBAAiB;AAE7C,MAAI,WAAW,SAAS,GAAG;AACzB,YAAQ,IAAI,sBAAsB,WAAW,KAAK,GAAG,CAAC,EAAE;AACxD,UAAM,cAAc,OAAO,CAAC,KAAK,MAAM,GAAG,UAAU,GAAG,EAAE,KAAK,WAAW,KAAK,OAAO,KAAK,CAAC;AAAA,EAC7F;AAEA,MAAI,UAAU,SAAS,GAAG;AACxB,YAAQ,IAAI,0BAA0B,UAAU,KAAK,GAAG,CAAC,EAAE;AAC3D,UAAM,cAAc,OAAO,CAAC,KAAK,GAAG,SAAS,GAAG,EAAE,KAAK,WAAW,KAAK,OAAO,KAAK,CAAC;AAAA,EACtF;AAEA,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,IAAI,6BAA6B,QAAQ,KAAK,GAAG,CAAC,EAAE;AAC5D,UAAM,cAAc,OAAO,CAAC,KAAK,MAAM,GAAG,OAAO,GAAG,EAAE,KAAK,WAAW,KAAK,OAAO,KAAK,CAAC;AAAA,EAC1F;AACF;AAOO,SAAS,gBAAgB,QAAsB;AACpD,QAAM,QAAkB,CAAC;AAEzB,MAAI,OAAO,gBAAgB,SAAS,GAAG;AACrC,UAAM,KAAK,kBAAkB;AAC7B,eAAW,KAAK,OAAO,iBAAiB;AACtC,YAAM,KAAK,KAAK,EAAE,IAAI,IAAI,EAAE,OAAO,EAAE;AAAA,IACvC;AAAA,EACF;AAEA,MAAI,OAAO,mBAAmB,SAAS,GAAG;AACxC,QAAI,MAAM,OAAQ,OAAM,KAAK,EAAE;AAC/B,UAAM,KAAK,qBAAqB;AAChC,eAAW,KAAK,OAAO,oBAAoB;AACzC,YAAM,KAAK,KAAK,EAAE,IAAI,IAAI,EAAE,OAAO,EAAE;AAAA,IACvC;AAAA,EACF;AAEA,MAAI,OAAO,uBAAuB,SAAS,GAAG;AAC5C,QAAI,MAAM,OAAQ,OAAM,KAAK,EAAE;AAC/B,UAAM,KAAK,yBAAyB;AACpC,eAAW,KAAK,OAAO,wBAAwB;AAC7C,YAAM,KAAK,KAAK,EAAE,IAAI,IAAI,EAAE,OAAO,EAAE;AAAA,IACvC;AAAA,EACF;AAEA,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,KAAK,+BAA+B;AAAA,EAC5C;AAEA,UAAQ,IAAI,MAAM,KAAK,IAAI,CAAC;AAC9B;;;ACzFA,OAAO,UAAU;;;ACyBV,SAAS,WAAW,QAAwB;AACjD,QAAM,IAAY;AAAA,IAChB,GAAG;AAAA,IACH,iBAAiB,CAAC,GAAG,OAAO,eAAe,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAAA,IACxF,oBAAoB,CAAC,GAAG,OAAO,kBAAkB,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAAA,IAC9F,wBAAwB,CAAC,GAAG,OAAO,sBAAsB,EAAE;AAAA,MAAK,CAAC,GAAG,MAClE,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,IAC7B;AAAA,EACF;AACA,SAAO,KAAK,UAAU,GAAG,MAAM,CAAC;AAClC;;;AC1BA,SAAS,MAAM,SAAmB,MAA0B;AAC1D,QAAM,SAAS,KAAK,QAAQ,KAAK,KAAK,CAAC;AACvC,QAAM,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,EAAE,KAAK,KAAK,CAAC;AACrD,QAAM,OAAO,KAAK,IAAI,CAAC,MAAM,KAAK,EAAE,KAAK,KAAK,CAAC,IAAI,EAAE,KAAK,IAAI;AAC9D,SAAO,CAAC,QAAQ,KAAK,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AACtD;AA6BO,SAAS,eACd,QAKQ;AACR,QAAM,QAAkB,CAAC;AACzB,QAAM,KAAK,cAAc;AACzB,QAAM,KAAK,EAAE;AAEb,MACE,OAAO,gBACP,OAAO,mBACN,OAAe,uBACf,OAAe,oBACf,OAAe,cAChB;AACA,UAAM,KAAK,qBAAqB;AAChC,QAAI,OAAO,aAAc,OAAM,KAAK,WAAW,OAAO,YAAY,EAAE;AACpE,QAAI,OAAO,gBAAiB,OAAM,KAAK,cAAc,OAAO,eAAe,EAAE;AAC7E,QAAK,OAAe;AAClB,YAAM,KAAK,kBAAmB,OAAe,mBAAmB,EAAE;AACpE,QAAK,OAAe;AAClB,YAAM,KAAK,eAAgB,OAAe,gBAAgB,EAAE;AAC9D,QAAK,OAAe,aAAc,OAAM,KAAK,WAAY,OAAe,YAAY,EAAE;AACtF,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,OAAO,gBAAgB,SAAS,GAAG;AACrC,UAAM,KAAK,oBAAoB;AAC/B,UAAM,OAAO,OAAO,gBAAgB,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,WAAW,IAAI,EAAE,iBAAiB,EAAE,CAAC;AAC/F,UAAM,KAAK,MAAM,CAAC,QAAQ,WAAW,MAAM,GAAG,IAAI,CAAC;AACnD,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,OAAO,mBAAmB,SAAS,GAAG;AACxC,UAAM,KAAK,uBAAuB;AAClC,UAAM,OAAO,OAAO,mBAAmB,IAAI,CAAC,MAAM;AAAA,MAChD,EAAE;AAAA,MACF,EAAE,WAAW;AAAA,MACb,EAAE,iBAAiB;AAAA,IACrB,CAAC;AACD,UAAM,KAAK,MAAM,CAAC,QAAQ,WAAW,MAAM,GAAG,IAAI,CAAC;AACnD,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,OAAO,uBAAuB,SAAS,GAAG;AAC5C,UAAM,KAAK,2BAA2B;AACtC,UAAM,OAAO,OAAO,uBAAuB,IAAI,CAAC,MAAM;AAAA,MACpD,EAAE;AAAA,MACF,EAAE,WAAW;AAAA,MACb,EAAE,iBAAiB;AAAA,IACrB,CAAC;AACD,UAAM,KAAK,MAAM,CAAC,QAAQ,WAAW,MAAM,GAAG,IAAI,CAAC;AACnD,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,oBAAoB;AAE/B,SAAO,MAAM,KAAK,IAAI;AACxB;;;AF3FA,eAAsB,aACpB,QACA,QACA,SACA,gBACe;AACf,QAAM,UACJ,WAAW,SACP,WAAW,MAAM,IACjB,eAAe,EAAE,GAAG,QAAQ,GAAI,kBAAkB,CAAC,EAAG,CAAC;AAE7D,MAAI,SAAS;AACX,UAAM,SAAS,KAAK,QAAQ,OAAO;AACnC,UAAM,EAAE,OAAO,UAAU,IAAI,MAAM,OAAO,aAAkB;AAE5D,UAAM,MAAM,QAAQ,EAAE,WAAW,KAAK,CAAC;AACvC,UAAM,UAAU,SAAS,SAAS,MAAM;AAExC,YAAQ,IAAI,mBAAmB,OAAO,EAAE;AAAA,EAC1C,OAAO;AACL,YAAQ,IAAI,OAAO;AAAA,EACrB;AACF;;;AGpCA,SAAS,gBAAgB;AACzB,OAAOC,WAAU;AAOV,SAAS,qBAAqB,UAA2B;AAC9D,QAAM,MAAMA,MAAK,QAAQ,QAAQ,EAAE,YAAY;AAC/C,SAAO,QAAQ,SAAS,QAAQ;AAClC;AASA,SAAS,2BAA2B,OAAiB,YAAmC;AACtF,QAAM,OAAsB,CAAC;AAC7B,MAAI,CAAC,MAAM,UAAU,KAAK,CAAC,MAAM,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,EAAG,QAAO;AAE5E,MAAI,IAAI,aAAa;AACrB,SAAO,IAAI,MAAM,UAAU,MAAM,CAAC,EAAE,KAAK,EAAE,WAAW,GAAG,GAAG;AAC1D,UAAM,OAAO,MAAM,CAAC,EACjB,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,CAAC,GAAG,KAAK,QAAQ,EAAE,QAAQ,KAAK,QAAQ,IAAI,SAAS,EAAE;AAEjE,UAAM,CAAC,OAAO,IAAI,UAAU,IAAI,gBAAgB,EAAE,IAAI;AACtD,QAAI,KAAM,MAAK,KAAK,EAAE,MAAM,SAAS,cAAc,CAAC;AACpD;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,oBAAoB,IAAoB;AACtD,QAAM,QAAQ,GAAG,MAAM,OAAO;AAE9B,QAAM,cAAc,CAAC,UACnB,MAAM,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,MAAM,MAAM,KAAK,GAAG,YAAY,CAAC;AAE/E,QAAM,eAAe,CAAC,QAA+B;AACnD,QAAI,MAAM,EAAG,QAAO,CAAC;AAErB,QAAI,IAAI,MAAM;AACd,WAAO,IAAI,MAAM,UAAU,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,WAAW,GAAG,EAAG;AAC7D,WAAO,2BAA2B,OAAO,CAAC;AAAA,EAC5C;AAEA,QAAM,kBAAkB,aAAa,YAAY,iBAAiB,CAAC;AACnE,QAAM,qBAAqB,aAAa,YAAY,oBAAoB,CAAC;AACzE,QAAM,yBAAyB,aAAa,YAAY,wBAAwB,CAAC;AAEjF,QAAM,SAAiB;AAAA,IACrB,gBAAgB;AAAA,IAChB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,SAAO;AACT;AASA,eAAsB,mBAAmB,YAAqC;AAC5E,QAAM,MAAM,MAAM,SAAS,YAAY,MAAM;AAE7C,MAAI,qBAAqB,UAAU,KAAK,IAAI,WAAW,cAAc,GAAG;AACtE,WAAO,oBAAoB,GAAG;AAAA,EAChC;AAEA,SAAO,KAAK,MAAM,GAAG;AACvB;;;ACxFA,SAAS,YAAAC,iBAAgB;AACzB,OAAOC,WAAU;;;ACEjB,eAAeC,oBAMb;AACA,QAAM,EAAE,SAAS,IAAI,MAAM,OAAO,eAAoB;AACtD,QAAM,EAAE,UAAU,IAAI,MAAM,OAAO,MAAW;AAC9C,SAAO,UAAU,QAAQ;AAC3B;AAkCA,eAAsB,MAAM,UAAwB,CAAC,GAAiB;AACpE,QAAM,OAAO,CAAC,MAAM,QAAQ;AAC5B,MAAI,QAAQ,OAAQ,MAAK,KAAK,UAAU;AACxC,MAAI,QAAQ,QAAS,MAAK,KAAK,YAAY;AAC3C,MAAI,QAAQ,OAAQ,MAAK,KAAK,WAAW;AAEzC,MAAI;AACF,UAAM,gBAAgB,MAAMA,kBAAiB;AAC7C,UAAM,EAAE,OAAO,IAAI,MAAM,cAAc,OAAO,MAAM;AAAA,MAClD,KAAK,QAAQ;AAAA,MACb,WAAW,KAAK,OAAO;AAAA,IACzB,CAAC;AACD,QAAI,UAAU,OAAO,KAAK,EAAG,QAAO,KAAK,MAAM,MAAM;AACrD,WAAO,CAAC;AAAA,EACV,SAAS,KAAU;AACjB,UAAM,SAAS,KAAK;AACpB,QAAI,OAAO,WAAW,YAAY,OAAO,KAAK,GAAG;AAC/C,UAAI;AACF,eAAO,KAAK,MAAM,MAAM;AAAA,MAC1B,SAAS,UAAU;AACjB,YAAI,QAAQ,IAAI,OAAO,SAAS,KAAK,GAAG;AACtC,kBAAQ,KAAK,+BAA+B,QAAQ;AAAA,QACtD;AAAA,MACF;AAAA,IACF;AACA,UAAM,SAAS,KAAK;AACpB,UAAM,MAAO,OAAO,WAAW,YAAY,OAAO,KAAK,KAAM,KAAK,WAAW;AAC7E,UAAM,IAAI,MAAM,kBAAkB,GAAG,EAAE;AAAA,EACzC;AACF;AAoBA,eAAsB,gBAAiC;AACrD,MAAI;AACF,UAAM,gBAAgB,MAAMA,kBAAiB;AAC7C,UAAM,EAAE,OAAO,IAAI,MAAM,cAAc,OAAO,CAAC,QAAQ,IAAI,CAAC;AAC5D,WAAO,OAAO,KAAK;AAAA,EACrB,SAAS,KAAU;AACjB,UAAM,SAAS,KAAK;AACpB,UAAM,MACH,OAAO,WAAW,YAAY,OAAO,KAAK,KAAM,KAAK,WAAW;AACnE,UAAM,IAAI,MAAM,uBAAuB,GAAG,EAAE;AAAA,EAC9C;AACF;;;AC3GA,OAAOC,WAAU;AACjB,SAAS,YAAAC,iBAAgB;AA4BzB,SAAS,WAAW,KAA4E;AAC9F,MAAI,CAAC,IAAK,QAAO,CAAC;AAClB,SAAO,OAAO,KAAK,GAAG,EACnB,IAAI,CAAC,UAAU,EAAE,MAAM,MAAM,IAAI,IAAI,EAAE,EAAE,EACzC,OAAO,CAAC,MAAM,KAAK,EAAE,IAAI;AAC9B;AAwBA,eAAsB,uBAAuB,MAAW,MAAyC;AAC/F,QAAM,aAAY,oBAAI,KAAK,GAAE,YAAY;AACzC,QAAM,SAAiB;AAAA,IACrB,gBAAgB;AAAA,IAChB;AAAA,IACA,cAAc,KAAK;AAAA,IACnB,iBAAiB,CAAC;AAAA,IAClB,oBAAoB,CAAC;AAAA,IACrB,wBAAwB,CAAC;AAAA,EAC3B;AAEA,MAAI,KAAK,YAAY,SAAS;AAC5B,QAAI,UAAe;AACnB,QAAI;AACF,YAAM,cAAcD,MAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG,cAAc;AACvE,YAAM,MAAM,MAAMC,UAAS,aAAa,MAAM;AAC9C,gBAAU,KAAK,MAAM,GAAG;AAAA,IAC1B,QAAQ;AAAA,IAGR;AACA,QAAI,SAAS,KAAM,QAAO,eAAe,QAAQ;AACjD,QAAI,SAAS,QAAS,QAAO,kBAAkB,QAAQ;AAEvD,UAAM,UAAU,MAAM;AACtB,UAAM,QAAQ,WAAW,OAAO;AAChC,UAAM,UAAU,IAAI,IAAI,OAAO,KAAM,SAAS,mBAA8C,CAAC,CAAC,CAAC;AAE/F,eAAW,EAAE,MAAM,KAAK,KAAK,OAAO;AAClC,YAAM,UAAW,QAAQ,KAAK,WAAY;AAC1C,YAAM,eACH,QAAQ,KAAK,QAASD,MAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG,gBAAgB,IAAI;AAClF,YAAM,MAAmB,EAAE,MAAM,SAAS,eAAe,aAAa;AACtE,UAAI,QAAQ,IAAI,IAAI,GAAG;AACrB,eAAO,uBAAuB,KAAK,GAAG;AAAA,MACxC,OAAO;AACL,eAAO,mBAAmB,KAAK,GAAG;AAAA,MACpC;AAAA,IACF;AAEA,WAAO,mBAAmB,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AACrE,WAAO,uBAAuB,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAAA,EAC3E,WAAW,KAAK,YAAY,UAAU;AACpC,UAAM,UAAU,MAAM;AACtB,UAAM,QAAQ,WAAW,OAAO;AAEhC,eAAW,EAAE,MAAM,KAAK,KAAK,OAAO;AAClC,YAAM,UAAW,QAAQ,KAAK,WAAY;AAC1C,YAAM,eAAgB,QAAQ,KAAK,QAASA,MAAK,KAAK,KAAK,cAAc,IAAI,IAAI;AACjF,YAAM,MAAmB,EAAE,MAAM,SAAS,eAAe,aAAa;AACtE,aAAO,gBAAgB,KAAK,GAAG;AAAA,IACjC;AAEA,WAAO,gBAAgB,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAAA,EACpE;AAEA,MAAI,KAAK,aAAa;AACpB,WAAO,OAAO;AAAA,EAChB;AAEA,SAAO;AACT;;;ACvHA,SAAS,YAAAE,iBAAgB;AACzB,OAAOC,WAAU;AACjB,SAAS,qBAAqB;AAKvB,SAAS,iBAAyB;AACvC,MAAI;AACF,UAAM,aAAa,cAAe,YAAoB,GAAG;AACzD,UAAM,iBAAiBA,MAAK,QAAQ,UAAU;AAC9C,WAAOA,MAAK,QAAQ,gBAAgB,MAAM,MAAM,cAAc;AAAA,EAChE,QAAQ;AACN,UAAM,MAAM,OAAO,cAAc,cAAc,YAAY,QAAQ,IAAI;AACvE,WAAOA,MAAK,QAAQ,KAAK,MAAM,cAAc;AAAA,EAC/C;AACF;AAKA,eAAsB,iBAAkC;AACtD,MAAI;AACF,UAAM,UAAU,eAAe;AAC/B,UAAM,MAAM,MAAMD,UAAS,SAAS,MAAM;AAC1C,UAAM,MAAM,KAAK,MAAM,GAAG;AAC1B,WAAO,IAAI,WAAW;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKO,IAAM,eAAe,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AHInC,eAAsB,cACpB,KACA,SACuB;AACvB,QAAM,cAAc,MAAM,eAAe;AACzC,QAAM,SAAS,CAAC,QAAQ;AACxB,QAAM,MAAM,QAAQ,OAAO,QAAQ,IAAI;AAEvC,QAAM,OAAO,MAAM,MAAM;AAAA,IACvB,QAAQ,QAAQ;AAAA,IAChB,SAAS,QAAQ,UAAU,QAAQ,QAAQ,OAAO,IAAI;AAAA,IACtD;AAAA,IACA;AAAA,EACF,CAAC;AAED,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI,QAAQ,SAAS;AACnB,QAAI;AACF,YAAM,SAAS,MAAME,UAASC,MAAK,KAAK,KAAK,cAAc,GAAG,MAAM;AACpE,YAAM,MAAM,KAAK,MAAM,MAAM;AAC7B,4BAAsB,IAAI;AAC1B,yBAAmB,IAAI;AACvB,UAAI,OAAO,IAAI,SAAS,SAAU,gBAAe,IAAI;AAAA,eAC5C,IAAI,QAAQ,OAAO,IAAI,KAAK,QAAQ,SAAU,gBAAe,IAAI,KAAK;AAAA,IACjF,QAAQ;AAAA,IAGR;AAAA,EACF;AAEA,QAAM,aAAa,QAAQ,WAAW,MAAM,cAAc,EAAE,MAAM,MAAM,MAAS,IAAI;AAErF,QAAM,SAAS,MAAM,uBAAuB,MAAM;AAAA,IAChD,SAAS;AAAA,IACT,aAAa,QAAQ,QAAQ,QAAQ;AAAA,IACrC,SAAS,QAAQ,QAAQ,OAAO;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,iBAAiB,EAAE,qBAAqB,kBAAkB,aAAa;AAC7E,SAAO,EAAE,QAAQ,eAAe;AAClC;;;ANlEA,SAAS,iBAAiB,KAAc,EAAE,aAAa,GAAuC;AAC5F,MACG;AAAA,IACC;AAAA,IACA;AAAA,IACA,CAAC,QAAS,QAAQ,OAAO,OAAO;AAAA,IAChC;AAAA,EACF,EACC,OAAO,yBAAyB,sBAAsB,EACtD,OAAO,eAAe,mDAAmD,KAAK;AAEjF,MAAI,cAAc;AAChB,QAAI,OAAO,cAAc,wCAAwC,KAAK;AAAA,EACxE;AAEA,SAAO;AACT;AAQO,SAAS,mBAAmB,SAA2B;AAC5D,QAAM,WAAW,QACd,QAAQ,SAAS,EAAE,WAAW,KAAK,CAAC,EACpC,YAAY,0DAA0D;AAEzE,mBAAiB,UAAU,EAAE,cAAc,KAAK,CAAC;AAEjD,WAAS,OAAO,OAAO,SAAS;AAC9B,UAAM,eAAgB,KAAK,gBAAgB;AAC3C,UAAM,UAAU,KAAK;AACrB,UAAM,WAAW,QAAQ,KAAK,QAAQ;AACtC,UAAM,UAAU,QAAQ,KAAK,OAAO;AAEpC,QAAI,eAAe;AACnB,QAAI,CAAC,WAAW,KAAK,gBAAgB,OAAO,KAAK,iBAAiB,UAAU;AAC1E,qBAAe,cAAc,YAAY;AAAA,IAC3C;AAEA,UAAM,EAAE,QAAQ,eAAe,IAAI,MAAM,cAAc,SAAS;AAAA,MAC9D;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,aAAa,QAAQ,cAAc,cAAc,cAAc;AAAA,EACvE,CAAC;AAED,SAAO;AACT;AAQO,SAAS,oBAAoB,SAA2B;AAC7D,QAAM,YAAY,QACf,QAAQ,QAAQ,EAChB,YAAY,kDAAkD;AAEjE,mBAAiB,WAAW,EAAE,cAAc,MAAM,CAAC;AAEnD,YAAU,OAAO,OAAO,SAAS;AAC/B,UAAM,eAAgB,KAAK,gBAAgB;AAC3C,UAAM,UAAU,KAAK;AACrB,UAAM,WAAW,QAAQ,KAAK,QAAQ;AAEtC,QAAI,eAAe;AACnB,QAAI,CAAC,WAAW,KAAK,gBAAgB,OAAO,KAAK,iBAAiB,UAAU;AAC1E,qBAAe,cAAc,YAAY;AAAA,IAC3C;AAEA,UAAM,EAAE,QAAQ,eAAe,IAAI,MAAM,cAAc,UAAU;AAAA,MAC/D;AAAA,MACA,SAAS;AAAA,MACT;AAAA,IACF,CAAC;AAED,UAAM,aAAa,QAAQ,cAAc,cAAc,cAAc;AAAA,EACvE,CAAC;AAED,SAAO;AACT;AAQO,SAAS,kBAAkB,SAA2B;AAC3D,QAAM,UAAU,QACb,QAAQ,MAAM,EACd;AAAA,IACC;AAAA,EACF,EACC,SAAS,YAAY,0CAA0C,iBAAiB,EAChF,OAAO,uBAAuB,wCAAwC,EACtE,OAAO,eAAe,0DAA0D,KAAK,EACrF,OAAO,iBAAiB,oCAAoC,KAAK;AAEpE,UAAQ,OAAO,OAAO,WAA+B,SAAc;AACjE,UAAM,SAAU,KAAK,UAAiC,aAAa;AACnE,UAAM,aAAaC,MAAK,QAAQ,QAAQ,IAAI,GAAG,MAAM;AAErD,QAAI;AACF,YAAM,SAAS,MAAM,mBAAmB,UAAU;AAElD,YAAM,YAAY,QAAQ,KAAK,OAAO;AACtC,YAAM,UAAU,QAAQ,KAAK,KAAK,KAAK,CAAC;AAExC,UAAI,SAAS;AACX,wBAAgB,MAAM;AAAA,MACxB;AACA,UAAI,WAAW;AACb,cAAM,kBAAkB,QAAQ,QAAQ,IAAI,CAAC;AAAA,MAC/C;AAAA,IACF,SAAS,KAAU;AACjB,YAAM,OAAO,qBAAqB,UAAU;AAC5C,YAAM,OAAO,OACT,qGACA;AACJ,cAAQ,MAAM,4BAA4B,UAAU,KAAK,KAAK,WAAW,GAAG,EAAE;AAC9E,cAAQ,MAAM,IAAI;AAClB,cAAQ,WAAW;AAAA,IACrB;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAOA,eAAsB,gBAAkC;AACtD,QAAM,UAAU,IAAI,QAAQ,EACzB,KAAK,KAAK,EACV,YAAY,4EAA4E,EACxF,QAAQ,MAAM,eAAe,CAAC;AAEjC,UAAQ,YAAY,aAAa;AAAA,EAAK,YAAY,EAAE;AAEpD,qBAAmB,OAAO;AAC1B,sBAAoB,OAAO;AAC3B,oBAAkB,OAAO;AAEzB,SAAO;AACT;;;AUvKA,eAAsB,IAAI,OAAO,QAAQ,MAAqB;AAC5D,QAAM,UAAU,MAAM,cAAc;AACpC,QAAM,QAAQ,WAAW,IAAI;AAC/B;AAEA,IAAM,gBAAgB,MAAM;AAC1B,MAAI;AACF,QAAI,OAAO,cAAY,eAAe,OAAO,WAAW,aAAa;AACnE,aAAQ,UAAgB,SAAS;AAAA,IACnC;AAEA,QAAI,OAAO,gBAAgB,aAAa;AACtC,aAAO,YAAY,QAAQ,UAAU,QAAQ,KAAK,CAAC,CAAC;AAAA,IACtD;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF,GAAG;AAEH,IAAI,cAAc;AAChB,MAAI,EAAE,MAAM,CAAC,UAAU;AACrB,YAAQ,MAAM,cAAc,KAAK;AACjC,YAAQ,WAAW;AAAA,EACrB,CAAC;AACH;","names":["path","path","readFile","path","getExecFileAsync","path","readFile","readFile","path","readFile","path","path"]}
1
+ {"version":3,"sources":["../src/cli/commands.ts","../src/cli/install.ts","../src/cli/output.ts","../src/report/json.ts","../src/report/md.ts","../src/cli/parser.ts","../src/cli/report.ts","../src/npm.ts","../src/transform.ts","../src/cli/utils.ts","../src/cli.ts"],"sourcesContent":["/**\n * @fileoverview CLI command definitions and handlers\n */\n\nimport path from 'node:path'\n\nimport { Command } from 'commander'\n\nimport type { OutputFormat } from '../types.js'\n\nimport { installFromReport, printFromReport } from './install.js'\nimport { outputReport } from './output.js'\nimport { isMarkdownReportFile, loadReportFromFile } from './parser.js'\nimport { produceReport } from './report.js'\nimport { ASCII_BANNER, getToolVersion } from './utils.js'\n\n/**\n * Adds common options to a command\n *\n * @param cmd - Command to add options to\n * @param options - Configuration for which options to add\n * @returns Modified command\n */\nfunction addCommonOptions(cmd: Command, { allowOmitDev }: { allowOmitDev: boolean }): Command {\n cmd\n .option(\n '-f, --output-format <format>',\n 'Output format: md or json',\n (val) => (val === 'md' ? 'md' : 'json'),\n 'json',\n )\n .option('-o, --out-file <path>', 'Write report to file')\n .option('--full-tree', 'Include full npm ls tree (omit depth=0 default)', false)\n\n if (allowOmitDev) {\n cmd.option('--omit-dev', 'Exclude devDependencies (local only)', false)\n }\n\n return cmd\n}\n\n/**\n * Creates the local command handler\n *\n * @param program - Commander program instance\n * @returns Command instance\n */\nexport function createLocalCommand(program: Command): Command {\n const localCmd = program\n .command('local', { isDefault: true })\n .description(\"Generate a report for the current project's dependencies\")\n\n addCommonOptions(localCmd, { allowOmitDev: true })\n\n localCmd.action(async (opts) => {\n const outputFormat = (opts.outputFormat ?? 'json') as OutputFormat\n const outFile = opts.outFile as string | undefined\n const fullTree = Boolean(opts.fullTree)\n const omitDev = Boolean(opts.omitDev)\n\n // Only set finalOutFile when explicitly provided via --out-file\n const finalOutFile = outFile\n\n const { report, markdownExtras } = await produceReport('local', {\n outputFormat,\n outFile: finalOutFile,\n fullTree,\n omitDev,\n })\n\n await outputReport(report, outputFormat, finalOutFile, markdownExtras)\n })\n\n return localCmd\n}\n\n/**\n * Creates the global command handler\n *\n * @param program - Commander program instance\n * @returns Command instance\n */\nexport function createGlobalCommand(program: Command): Command {\n const globalCmd = program\n .command('global')\n .description('Generate a report of globally installed packages')\n\n addCommonOptions(globalCmd, { allowOmitDev: false })\n\n globalCmd.action(async (opts) => {\n const outputFormat = (opts.outputFormat ?? 'json') as OutputFormat\n const outFile = opts.outFile as string | undefined\n const fullTree = Boolean(opts.fullTree)\n\n // Only set finalOutFile when explicitly provided via --out-file\n const finalOutFile = outFile\n\n const { report, markdownExtras } = await produceReport('global', {\n outputFormat,\n outFile: finalOutFile,\n fullTree,\n })\n\n await outputReport(report, outputFormat, finalOutFile, markdownExtras)\n })\n\n return globalCmd\n}\n\n/**\n * Creates the read command handler\n *\n * @param program - Commander program instance\n * @returns Command instance\n */\nexport function createReadCommand(program: Command): Command {\n const readCmd = program\n .command('read')\n .description(\n 'Read a previously generated report (JSON or Markdown) and either print package names or install them',\n )\n .argument('[report]', 'Path to report file (JSON or Markdown)', 'gex-report.json')\n .option('-r, --report <path>', 'Path to report file (JSON or Markdown)')\n .option('-p, --print', 'Print package names/versions from the report (default)', false)\n .option('-i, --install', 'Install packages from the report', false)\n\n readCmd.action(async (reportArg: string | undefined, opts: any) => {\n const chosen = (opts.report as string | undefined) || reportArg || 'gex-report.json'\n const reportPath = path.resolve(process.cwd(), chosen)\n\n try {\n const parsed = await loadReportFromFile(reportPath)\n\n const doInstall = Boolean(opts.install)\n const doPrint = Boolean(opts.print) || !doInstall\n\n if (doPrint) {\n printFromReport(parsed)\n }\n if (doInstall) {\n await installFromReport(parsed, process.cwd())\n }\n } catch (err: any) {\n const isMd = isMarkdownReportFile(reportPath)\n const hint = isMd\n ? 'Try generating a JSON report with: gex global -f json -o global.json, then: gex read global.json'\n : 'Specify a report path with: gex read <path-to-report.json>'\n console.error(`Failed to read report at ${reportPath}: ${err?.message || err}`)\n console.error(hint)\n process.exitCode = 1\n }\n })\n\n return readCmd\n}\n\n/**\n * Creates and configures the main CLI program\n *\n * @returns Configured Commander program\n */\nexport async function createProgram(): Promise<Command> {\n const program = new Command()\n .name('gex')\n .description('GEX: Dependency auditing and documentation for Node.js (local and global).')\n .version(await getToolVersion())\n\n program.addHelpText('beforeAll', `\\n${ASCII_BANNER}`)\n\n createLocalCommand(program)\n createGlobalCommand(program)\n createReadCommand(program)\n\n return program\n}\n","/**\n * @fileoverview Package installation utilities for CLI\n */\n\nimport type { Report } from '../types.js'\n\n/**\n * Lazily obtain a promisified execFile so tests can mock built-ins reliably.\n */\nasync function getExecFileAsync(): Promise<\n (\n command: string,\n args?: readonly string[] | null,\n options?: any,\n ) => Promise<{ stdout: string; stderr: string }>\n> {\n const { execFile } = await import('node:child_process')\n const { promisify } = await import('node:util')\n return promisify(execFile) as any\n}\n\n/**\n * Installs packages from a report to the local environment\n *\n * @param report - The report containing packages to install\n * @param cwd - Current working directory for installation\n * @throws {Error} If npm installation fails\n */\nexport async function installFromReport(report: Report, cwd: string): Promise<void> {\n const globalPkgs = report.global_packages.map((p) => `${p.name}@${p.version}`).filter(Boolean)\n const localPkgs = report.local_dependencies.map((p) => `${p.name}@${p.version}`).filter(Boolean)\n const devPkgs = report.local_dev_dependencies.map((p) => `${p.name}@${p.version}`).filter(Boolean)\n\n if (globalPkgs.length === 0 && localPkgs.length === 0 && devPkgs.length === 0) {\n console.log('No packages to install from report.')\n return\n }\n\n // Acquire execFileAsync once per run to keep logs grouped, while still mockable in tests\n const execFileAsync = await getExecFileAsync()\n\n if (globalPkgs.length > 0) {\n console.log(`Installing global: ${globalPkgs.join(' ')}`)\n await execFileAsync('npm', ['i', '-g', ...globalPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 })\n }\n\n if (localPkgs.length > 0) {\n console.log(`Installing local deps: ${localPkgs.join(' ')}`)\n await execFileAsync('npm', ['i', ...localPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 })\n }\n\n if (devPkgs.length > 0) {\n console.log(`Installing local devDeps: ${devPkgs.join(' ')}`)\n await execFileAsync('npm', ['i', '-D', ...devPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 })\n }\n}\n\n/**\n * Prints packages from a report to the console\n *\n * @param report - The report to print packages from\n */\nexport function printFromReport(report: Report): void {\n const lines: string[] = []\n\n if (report.global_packages.length > 0) {\n lines.push('Global Packages:')\n for (const p of report.global_packages) {\n lines.push(`- ${p.name}@${p.version}`)\n }\n }\n\n if (report.local_dependencies.length > 0) {\n if (lines.length) lines.push('')\n lines.push('Local Dependencies:')\n for (const p of report.local_dependencies) {\n lines.push(`- ${p.name}@${p.version}`)\n }\n }\n\n if (report.local_dev_dependencies.length > 0) {\n if (lines.length) lines.push('')\n lines.push('Local Dev Dependencies:')\n for (const p of report.local_dev_dependencies) {\n lines.push(`- ${p.name}@${p.version}`)\n }\n }\n\n if (lines.length === 0) {\n lines.push('(no packages found in report)')\n }\n\n console.log(lines.join('\\n'))\n}\n","/**\n * @fileoverview Report output utilities for CLI\n */\n\nimport path from 'node:path'\n\nimport { renderJson } from '../report/json.js'\nimport { renderMarkdown } from '../report/md.js'\nimport type { OutputFormat, Report } from '../types.js'\n\n/**\n * Outputs a report to console or file\n *\n * @param report - The report to output\n * @param format - Output format ('json' or 'md')\n * @param outFile - Optional file path to write to\n * @param markdownExtras - Additional metadata for markdown rendering\n */\nexport async function outputReport(\n report: Report,\n format: OutputFormat,\n outFile?: string,\n markdownExtras?: any,\n): Promise<void> {\n const content =\n format === 'json'\n ? renderJson(report)\n : renderMarkdown({ ...report, ...(markdownExtras || {}) })\n\n if (outFile) {\n const outDir = path.dirname(outFile)\n const { mkdir, writeFile } = await import('node:fs/promises')\n\n await mkdir(outDir, { recursive: true })\n await writeFile(outFile, content, 'utf8')\n\n console.log(`Wrote report to ${outFile}`)\n } else {\n console.log(content)\n }\n}\n","/**\n * @fileoverview JSON report rendering utilities\n */\n\nimport type { Report } from '../types.js'\n\n/**\n * Renders a Report object as formatted JSON string\n *\n * @param report - Report object to render\n * @returns Pretty-printed JSON string with consistent package ordering\n *\n * @example\n * ```typescript\n * import { renderJson } from './report/json.js'\n *\n * const report = {\n * report_version: '1.0',\n * timestamp: new Date().toISOString(),\n * tool_version: '0.3.2',\n * global_packages: [],\n * local_dependencies: [{ name: 'axios', version: '1.6.0', resolved_path: '/path/to/axios' }],\n * local_dev_dependencies: []\n * }\n *\n * const jsonOutput = renderJson(report)\n * console.log(jsonOutput) // Pretty-printed JSON\n * ```\n */\nexport function renderJson(report: Report): string {\n const r: Report = {\n ...report,\n global_packages: [...report.global_packages].sort((a, b) => a.name.localeCompare(b.name)),\n local_dependencies: [...report.local_dependencies].sort((a, b) => a.name.localeCompare(b.name)),\n local_dev_dependencies: [...report.local_dev_dependencies].sort((a, b) =>\n a.name.localeCompare(b.name),\n ),\n }\n return JSON.stringify(r, null, 2)\n}\n","/**\n * @fileoverview Markdown report rendering utilities\n */\n\nimport type { Report } from '../types.js'\n\n/**\n * Creates a markdown table from headers and row data\n *\n * @param headers - Array of table header strings\n * @param rows - Array of row data (each row is array of strings)\n * @returns Formatted markdown table string\n */\nfunction table(headers: string[], rows: string[][]): string {\n const header = `| ${headers.join(' | ')} |`\n const sep = `| ${headers.map(() => '---').join(' | ')} |`\n const body = rows.map((r) => `| ${r.join(' | ')} |`).join('\\n')\n return [header, sep, body].filter(Boolean).join('\\n')\n}\n\n/**\n * Renders a Report object as formatted Markdown\n *\n * @param report - Report object with optional project metadata\n * @returns Formatted Markdown string with tables and sections\n *\n * @example\n * ```typescript\n * import { renderMarkdown } from './report/md.js'\n *\n * const report = {\n * report_version: '1.0',\n * timestamp: new Date().toISOString(),\n * tool_version: '0.3.2',\n * project_name: 'my-project',\n * global_packages: [],\n * local_dependencies: [\n * { name: 'axios', version: '1.6.0', resolved_path: '/path/to/axios' }\n * ],\n * local_dev_dependencies: [],\n * project_description: 'My awesome project'\n * }\n *\n * const markdown = renderMarkdown(report)\n * console.log(markdown) // Formatted markdown with tables\n * ```\n */\nexport function renderMarkdown(\n report: Report & {\n project_description?: string\n project_homepage?: string\n project_bugs?: string\n },\n): string {\n const lines: string[] = []\n lines.push('# GEX Report')\n lines.push('')\n\n if (\n report.project_name ||\n report.project_version ||\n (report as any).project_description ||\n (report as any).project_homepage ||\n (report as any).project_bugs\n ) {\n lines.push('## Project Metadata')\n if (report.project_name) lines.push(`- Name: ${report.project_name}`)\n if (report.project_version) lines.push(`- Version: ${report.project_version}`)\n if ((report as any).project_description)\n lines.push(`- Description: ${(report as any).project_description}`)\n if ((report as any).project_homepage)\n lines.push(`- Homepage: ${(report as any).project_homepage}`)\n if ((report as any).project_bugs) lines.push(`- Bugs: ${(report as any).project_bugs}`)\n lines.push('')\n }\n\n if (report.global_packages.length > 0) {\n lines.push('## Global Packages')\n const rows = report.global_packages.map((p) => [p.name, p.version || '', p.resolved_path || ''])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n if (report.local_dependencies.length > 0) {\n lines.push('## Local Dependencies')\n const rows = report.local_dependencies.map((p) => [\n p.name,\n p.version || '',\n p.resolved_path || '',\n ])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n if (report.local_dev_dependencies.length > 0) {\n lines.push('## Local Dev Dependencies')\n const rows = report.local_dev_dependencies.map((p) => [\n p.name,\n p.version || '',\n p.resolved_path || '',\n ])\n lines.push(table(['Name', 'Version', 'Path'], rows))\n lines.push('')\n }\n\n lines.push('---')\n lines.push('_Generated by GEX_')\n\n return lines.join('\\n')\n}\n","/**\n * @fileoverview Report parsing utilities for CLI\n */\n\nimport { readFile } from 'node:fs/promises'\nimport path from 'node:path'\n\nimport type { PackageInfo, Report } from '../types.js'\n\n/**\n * Checks if a file path indicates a markdown report\n */\nexport function isMarkdownReportFile(filePath: string): boolean {\n const ext = path.extname(filePath).toLowerCase()\n return ext === '.md' || ext === '.markdown'\n}\n\n/**\n * Parses a markdown table and extracts package information\n *\n * @param lines - Array of file lines\n * @param startIndex - Index where table starts\n * @returns Array of package information\n */\nfunction parseMarkdownPackagesTable(lines: string[], startIndex: number): PackageInfo[] {\n const rows: PackageInfo[] = []\n if (!lines[startIndex] || !lines[startIndex].trim().startsWith('|')) return rows\n\n let i = startIndex + 2\n while (i < lines.length && lines[i].trim().startsWith('|')) {\n const cols = lines[i]\n .split('|')\n .map((c) => c.trim())\n .filter((_, idx, arr) => !(idx === 0 || idx === arr.length - 1))\n\n const [name = '', version = '', resolved_path = ''] = cols\n if (name) rows.push({ name, version, resolved_path })\n i++\n }\n return rows\n}\n\n/**\n * Parses a markdown report and converts it to a Report object\n *\n * @param md - Markdown content to parse\n * @returns Parsed Report object\n */\nexport function parseMarkdownReport(md: string): Report {\n const lines = md.split(/\\r?\\n/)\n\n const findSection = (title: string) =>\n lines.findIndex((l) => l.trim().toLowerCase() === `## ${title}`.toLowerCase())\n\n const parseSection = (idx: number): PackageInfo[] => {\n if (idx < 0) return []\n\n let i = idx + 1\n while (i < lines.length && !lines[i].trim().startsWith('|')) i++\n return parseMarkdownPackagesTable(lines, i)\n }\n\n const global_packages = parseSection(findSection('Global Packages'))\n const local_dependencies = parseSection(findSection('Local Dependencies'))\n const local_dev_dependencies = parseSection(findSection('Local Dev Dependencies'))\n\n const report: Report = {\n report_version: '1.0',\n timestamp: new Date().toISOString(),\n tool_version: 'unknown',\n global_packages,\n local_dependencies,\n local_dev_dependencies,\n }\n return report\n}\n\n/**\n * Loads and parses a report file (JSON or Markdown)\n *\n * @param reportPath - Path to the report file\n * @returns Parsed Report object\n * @throws {Error} If file cannot be read or parsed\n */\nexport async function loadReportFromFile(reportPath: string): Promise<Report> {\n const raw = await readFile(reportPath, 'utf8')\n\n if (isMarkdownReportFile(reportPath) || raw.startsWith('# GEX Report')) {\n return parseMarkdownReport(raw)\n }\n\n return JSON.parse(raw) as Report\n}\n","/**\n * @fileoverview Report generation utilities for CLI\n */\n\nimport { readFile } from 'node:fs/promises'\nimport path from 'node:path'\n\nimport { npmLs, npmRootGlobal } from '../npm.js'\nimport { buildReportFromNpmTree } from '../transform.js'\nimport type { OutputFormat, Report } from '../types.js'\n\nimport { getToolVersion } from './utils.js'\n\n/**\n * Options for report generation\n */\nexport interface ReportOptions {\n outputFormat: OutputFormat\n outFile?: string\n fullTree?: boolean\n omitDev?: boolean\n cwd?: string\n}\n\n/**\n * Result of report generation including markdown extras\n */\nexport interface ReportResult {\n report: Report\n markdownExtras?: {\n project_description?: string\n project_homepage?: string\n project_bugs?: string\n }\n}\n\n/**\n * Produces a dependency report for local or global context\n *\n * @param ctx - Context for report generation ('local' or 'global')\n * @param options - Report generation options\n * @returns Report and optional markdown extras\n */\nexport async function produceReport(\n ctx: 'local' | 'global',\n options: ReportOptions,\n): Promise<ReportResult> {\n const toolVersion = await getToolVersion()\n const depth0 = !options.fullTree\n const cwd = options.cwd || process.cwd()\n\n const tree = await npmLs({\n global: ctx === 'global',\n omitDev: ctx === 'local' ? Boolean(options.omitDev) : false,\n depth0,\n cwd,\n })\n\n let project_description: string | undefined\n let project_homepage: string | undefined\n let project_bugs: string | undefined\n\n if (ctx === 'local') {\n try {\n const pkgRaw = await readFile(path.join(cwd, 'package.json'), 'utf8')\n const pkg = JSON.parse(pkgRaw)\n project_description = pkg.description\n project_homepage = pkg.homepage\n if (typeof pkg.bugs === 'string') project_bugs = pkg.bugs\n else if (pkg.bugs && typeof pkg.bugs.url === 'string') project_bugs = pkg.bugs.url\n } catch {\n // Ignore errors reading local package.json (e.g., file missing or invalid JSON)\n void 0\n }\n }\n\n const globalRoot = ctx === 'global' ? await npmRootGlobal().catch(() => undefined) : undefined\n\n const report = await buildReportFromNpmTree(tree, {\n context: ctx,\n includeTree: Boolean(options.fullTree),\n omitDev: Boolean(options.omitDev),\n cwd,\n toolVersion,\n globalRoot,\n })\n\n const markdownExtras = { project_description, project_homepage, project_bugs }\n return { report, markdownExtras }\n}\n","/**\n * @fileoverview npm command execution utilities for dependency analysis\n */\n\n/**\n * Lazily obtain a promisified execFile so tests can mock built-ins reliably.\n */\nasync function getExecFileAsync(): Promise<\n (\n command: string,\n args?: readonly string[] | null,\n options?: any,\n ) => Promise<{ stdout: string; stderr: string }>\n> {\n const { execFile } = await import('node:child_process')\n const { promisify } = await import('node:util')\n return promisify(execFile) as any\n}\n\n/**\n * Options for npm ls command execution\n */\nexport type NpmLsOptions = {\n /** Whether to list global packages */\n global?: boolean\n /** Whether to omit devDependencies */\n omitDev?: boolean\n /** Whether to use depth=0 for faster execution */\n depth0?: boolean\n /** Current working directory for command execution */\n cwd?: string\n}\n\n/**\n * Executes npm ls command and returns parsed dependency tree\n *\n * @param options - Configuration options for npm ls command\n * @returns Promise resolving to npm dependency tree object\n * @throws {Error} If npm command fails or output cannot be parsed\n *\n * @example\n * ```typescript\n * import { npmLs } from './npm.js'\n *\n * // Get local dependencies with devDependencies omitted\n * const tree = await npmLs({ omitDev: true, depth0: true })\n *\n * // Get global packages\n * const globalTree = await npmLs({ global: true })\n * ```\n */\nexport async function npmLs(options: NpmLsOptions = {}): Promise<any> {\n const args = ['ls', '--json']\n if (options.global) args.push('--global')\n if (options.omitDev) args.push('--omit=dev')\n if (options.depth0) args.push('--depth=0')\n\n try {\n const execFileAsync = await getExecFileAsync()\n const { stdout } = await execFileAsync('npm', args, {\n cwd: options.cwd,\n maxBuffer: 10 * 1024 * 1024,\n })\n if (stdout && stdout.trim()) return JSON.parse(stdout)\n return {}\n } catch (err: any) {\n const stdout = err?.stdout\n if (typeof stdout === 'string' && stdout.trim()) {\n try {\n return JSON.parse(stdout)\n } catch (parseErr) {\n if (process.env.DEBUG?.includes('gex')) {\n console.warn('npm ls stdout parse failed:', parseErr)\n }\n }\n }\n const stderr = err?.stderr\n const msg = (typeof stderr === 'string' && stderr.trim()) || err?.message || 'npm ls failed'\n throw new Error(`npm ls failed: ${msg}`)\n }\n}\n\n/**\n * Gets the global npm root directory path\n *\n * @returns Promise resolving to the global npm root path\n * @throws {Error} If npm root -g command fails\n *\n * @example\n * ```typescript\n * import { npmRootGlobal } from './npm.js'\n *\n * try {\n * const globalRoot = await npmRootGlobal()\n * console.log('Global npm root:', globalRoot)\n * } catch (error) {\n * console.error('Failed to get global root:', error.message)\n * }\n * ```\n */\nexport async function npmRootGlobal(): Promise<string> {\n try {\n const execFileAsync = await getExecFileAsync()\n const { stdout } = await execFileAsync('npm', ['root', '-g'])\n return stdout.trim()\n } catch (err: any) {\n const stderr = err?.stderr\n const msg =\n (typeof stderr === 'string' && stderr.trim()) || err?.message || 'npm root -g failed'\n throw new Error(`npm root -g failed: ${msg}`)\n }\n}\n","/**\n * @fileoverview Data transformation utilities for converting npm tree data into reports\n */\n\nimport path from 'node:path'\nimport { readFile } from 'node:fs/promises'\n\nimport type { PackageInfo, Report } from './types.js'\n\n/**\n * Options for report generation and normalization\n */\nexport type NormalizeOptions = {\n /** Context for report generation ('local' or 'global') */\n context: 'local' | 'global'\n /** Whether to include the full npm dependency tree */\n includeTree?: boolean\n /** Whether to omit devDependencies (local context only) */\n omitDev?: boolean\n /** Current working directory */\n cwd?: string\n /** Tool version to include in report */\n toolVersion: string\n /** Global npm root directory path */\n globalRoot?: string\n}\n\n/**\n * Converts npm dependency object to array of package entries\n *\n * @param obj - npm dependency object from npm ls output\n * @returns Array of name/node pairs for packages\n */\nfunction toPkgArray(obj: Record<string, any> | undefined | null): { name: string; node: any }[] {\n if (!obj) return []\n return Object.keys(obj)\n .map((name) => ({ name, node: obj[name] }))\n .filter((p) => p && p.node)\n}\n\n/**\n * Builds a GEX report from npm ls tree output\n *\n * @param tree - Raw npm ls command output\n * @param opts - Report generation options\n * @returns Promise resolving to a formatted Report object\n *\n * @example\n * ```typescript\n * import { buildReportFromNpmTree } from './transform.js'\n * import { npmLs } from './npm.js'\n *\n * const tree = await npmLs({ depth0: true })\n * const report = await buildReportFromNpmTree(tree, {\n * context: 'local',\n * toolVersion: '0.3.2',\n * cwd: process.cwd()\n * })\n *\n * console.log(`Found ${report.local_dependencies.length} dependencies`)\n * ```\n */\nexport async function buildReportFromNpmTree(tree: any, opts: NormalizeOptions): Promise<Report> {\n const timestamp = new Date().toISOString()\n const report: Report = {\n report_version: '1.0',\n timestamp,\n tool_version: opts.toolVersion,\n global_packages: [],\n local_dependencies: [],\n local_dev_dependencies: [],\n }\n\n if (opts.context === 'local') {\n let pkgMeta: any = null\n try {\n const pkgJsonPath = path.join(opts.cwd || process.cwd(), 'package.json')\n const raw = await readFile(pkgJsonPath, 'utf8')\n pkgMeta = JSON.parse(raw)\n } catch {\n // Ignore errors reading/parsing package.json; fall back to undefined metadata\n void 0\n }\n if (pkgMeta?.name) report.project_name = pkgMeta.name\n if (pkgMeta?.version) report.project_version = pkgMeta.version\n\n const depsObj = tree?.dependencies as Record<string, any> | undefined\n const items = toPkgArray(depsObj)\n const devKeys = new Set(Object.keys((pkgMeta?.devDependencies as Record<string, string>) || {}))\n\n for (const { name, node } of items) {\n const version = (node && node.version) || ''\n const resolvedPath =\n (node && node.path) || path.join(opts.cwd || process.cwd(), 'node_modules', name)\n const pkg: PackageInfo = { name, version, resolved_path: resolvedPath }\n if (devKeys.has(name)) {\n report.local_dev_dependencies.push(pkg)\n } else {\n report.local_dependencies.push(pkg)\n }\n }\n\n report.local_dependencies.sort((a, b) => a.name.localeCompare(b.name))\n report.local_dev_dependencies.sort((a, b) => a.name.localeCompare(b.name))\n } else if (opts.context === 'global') {\n const depsObj = tree?.dependencies as Record<string, any> | undefined\n const items = toPkgArray(depsObj)\n\n for (const { name, node } of items) {\n const version = (node && node.version) || ''\n const resolvedPath = (node && node.path) || path.join(opts.globalRoot || '', name)\n const pkg: PackageInfo = { name, version, resolved_path: resolvedPath }\n report.global_packages.push(pkg)\n }\n\n report.global_packages.sort((a, b) => a.name.localeCompare(b.name))\n }\n\n if (opts.includeTree) {\n report.tree = tree\n }\n\n return report\n}\n","/**\n * @fileoverview CLI utility functions for version handling and path resolution\n */\n\nimport { readFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\n/**\n * Gets the path to package.json for version resolution\n */\nexport function getPkgJsonPath(): string {\n try {\n const __filename = fileURLToPath((import.meta as any).url)\n const __dirnameLocal = path.dirname(__filename)\n return path.resolve(__dirnameLocal, '..', '..', 'package.json')\n } catch {\n const dir = typeof __dirname !== 'undefined' ? __dirname : process.cwd()\n return path.resolve(dir, '..', 'package.json')\n }\n}\n\n/**\n * Gets the current tool version from package.json\n */\nexport async function getToolVersion(): Promise<string> {\n try {\n const pkgPath = getPkgJsonPath()\n const raw = await readFile(pkgPath, 'utf8')\n const pkg = JSON.parse(raw)\n return pkg.version || '0.0.0'\n } catch {\n return '0.0.0'\n }\n}\n\n/**\n * ASCII banner for the CLI\n */\nexport const ASCII_BANNER = String.raw`\n ________ __\n / _____/ ____ _____/ |_ ____ ____\n/ \\ ___ / _ \\ / _ \\ __\\/ __ \\ / \\\n\\ \\_\\ ( <_> | <_> ) | \\ ___/| | \\\n \\______ /\\____/ \\____/|__| \\___ >___| /\n \\/ \\/ \\/\n GEX\n`\n","/**\n * @fileoverview Main CLI entry point for GEX dependency auditing tool\n */\n\nimport { createProgram } from './cli/commands.js'\n\n/**\n * Main CLI runner function\n *\n * @param argv - Command line arguments (defaults to process.argv)\n */\nexport async function run(argv = process.argv): Promise<void> {\n const program = await createProgram()\n await program.parseAsync(argv)\n}\n\nconst isMainModule = (() => {\n try {\n if (typeof require !== 'undefined' && typeof module !== 'undefined') {\n return (require as any).main === module\n }\n\n if (typeof import.meta !== 'undefined') {\n return import.meta.url === `file://${process.argv[1]}`\n }\n return false\n } catch {\n return false\n }\n})()\n\nif (isMainModule) {\n run().catch((error) => {\n console.error('CLI error:', error)\n process.exitCode = 1\n })\n}\n"],"mappings":"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","names":["path","path","readFile","path","getExecFileAsync","path","readFile","readFile","path","readFile","path","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yabasha/gex",
3
- "version": "0.3.3",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "description": "A CLI tool for auditing and documenting your Node.js package environment, generating comprehensive reports of global and local dependencies.",
6
6
  "type": "module",