@yabasha/gex 0.3.2 → 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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Library API entry.\n * Export functions here for consumers who import your package.\n */\n\nexport function greet(name: string): string {\n return `Hello, ${name}!`\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAKO,SAAS,MAAM,MAAsB;AAC1C,SAAO,UAAU,IAAI;AACvB;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/npm.ts","../src/transform.ts","../src/report/json.ts","../src/report/md.ts","../src/validators.ts"],"sourcesContent":["/**\n * @fileoverview Library API for GEX - Node.js dependency auditing and reporting tool\n * @version 0.3.2\n */\n\nimport { readFile } from 'node:fs/promises'\nimport { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport path from 'node:path'\n\nimport { npmLs, npmRootGlobal } from './npm.js'\nimport { buildReportFromNpmTree } from './transform.js'\nimport { renderJson } from './report/json.js'\nimport { renderMarkdown } from './report/md.js'\nimport { npmRateLimiter, validateFilePath, validateOutputFormat } from './validators.js'\nimport type { OutputFormat, PackageInfo, Report } from './types.js'\n\nconst execFileAsync = promisify(execFile)\n\nexport type { Report, PackageInfo, OutputFormat } from './types.js'\nexport { ValidationError } from './validators.js'\n\n/**\n * Options for generating local dependency reports\n */\nexport interface LocalReportOptions {\n /** Current working directory (defaults to process.cwd()) */\n cwd?: string\n /** Whether to exclude devDependencies */\n omitDev?: boolean\n /** Whether to use depth=0 for faster execution */\n depth0?: boolean\n /** Whether to include the full npm ls tree in the report */\n includeTree?: boolean\n /** Tool version to include in report metadata */\n toolVersion?: string\n}\n\n/**\n * Options for generating global dependency reports\n */\nexport interface GlobalReportOptions {\n /** Whether to use depth=0 for faster execution */\n depth0?: boolean\n /** Whether to include the full npm ls tree in the report */\n includeTree?: boolean\n /** Tool version to include in report metadata */\n toolVersion?: string\n}\n\n/**\n * Options for installing packages from a report\n */\nexport interface InstallOptions {\n /** Current working directory (defaults to process.cwd()) */\n cwd?: string\n /** Whether to perform a dry run (log commands without executing) */\n dryRun?: boolean\n}\n\n/**\n * Generates a dependency report for the local project\n *\n * @param options Configuration options for the report generation\n * @returns Promise that resolves to a Report object\n * @throws {ValidationError} If options are invalid\n * @throws {Error} If npm operations fail\n *\n * @example\n * ```typescript\n * import { generateLocalReport } from '@yabasha/gex'\n *\n * const report = await generateLocalReport({\n * omitDev: true,\n * depth0: true\n * })\n *\n * console.log(`Found ${report.local_dependencies.length} dependencies`)\n * ```\n */\nexport async function generateLocalReport(options: LocalReportOptions = {}): Promise<Report> {\n await npmRateLimiter.throttle()\n\n const cwd = options.cwd ? validateFilePath(options.cwd) : process.cwd()\n const toolVersion = options.toolVersion || (await getToolVersion())\n\n const tree = await npmLs({\n global: false,\n omitDev: options.omitDev,\n depth0: options.depth0,\n cwd,\n })\n\n return buildReportFromNpmTree(tree, {\n context: 'local',\n includeTree: options.includeTree,\n omitDev: options.omitDev,\n cwd,\n toolVersion,\n })\n}\n\n/**\n * Generates a dependency report for globally installed packages\n *\n * @param options Configuration options for the report generation\n * @returns Promise that resolves to a Report object\n * @throws {ValidationError} If options are invalid\n * @throws {Error} If npm operations fail\n *\n * @example\n * ```typescript\n * import { generateGlobalReport } from '@yabasha/gex'\n *\n * const report = await generateGlobalReport({ depth0: true })\n * console.log(`Found ${report.global_packages.length} global packages`)\n * ```\n */\nexport async function generateGlobalReport(options: GlobalReportOptions = {}): Promise<Report> {\n await npmRateLimiter.throttle()\n\n const toolVersion = options.toolVersion || (await getToolVersion())\n const globalRoot = await npmRootGlobal().catch(() => undefined)\n\n const tree = await npmLs({\n global: true,\n depth0: options.depth0,\n })\n\n return buildReportFromNpmTree(tree, {\n context: 'global',\n includeTree: options.includeTree,\n toolVersion,\n globalRoot,\n })\n}\n\n/**\n * Formats a report object as a string in the specified format\n *\n * @param report The report object to format\n * @param format The output format ('json' or 'md')\n * @param markdownExtras Additional metadata for markdown formatting\n * @returns Formatted report as a string\n * @throws {ValidationError} If format is invalid\n *\n * @example\n * ```typescript\n * import { generateLocalReport, formatReport } from '@yabasha/gex'\n *\n * const report = await generateLocalReport()\n * const jsonOutput = formatReport(report, 'json')\n * const markdownOutput = formatReport(report, 'md', {\n * project_description: 'My awesome project'\n * })\n * ```\n */\nexport function formatReport(\n report: Report,\n format: OutputFormat,\n markdownExtras?: {\n project_description?: string\n project_homepage?: string\n project_bugs?: string\n },\n): string {\n const validatedFormat = validateOutputFormat(format)\n\n if (validatedFormat === 'json') {\n return renderJson(report)\n } else {\n return renderMarkdown({ ...report, ...(markdownExtras || {}) })\n }\n}\n\n/**\n * Installs packages listed in a report\n *\n * @param report The report containing packages to install\n * @param options Installation options\n * @returns Promise that resolves when installation is complete\n * @throws {ValidationError} If options are invalid\n * @throws {Error} If npm installation fails\n *\n * @example\n * ```typescript\n * import { parseReportFile, installPackagesFromReport } from '@yabasha/gex'\n *\n * const report = await parseReportFile('./gex-report.json')\n * await installPackagesFromReport(report, { dryRun: true })\n * ```\n */\nexport async function installPackagesFromReport(\n report: Report,\n options: InstallOptions = {},\n): Promise<void> {\n const cwd = options.cwd ? validateFilePath(options.cwd) : process.cwd()\n\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 return\n }\n\n if (options.dryRun) {\n if (globalPkgs.length > 0) {\n console.log(`[DRY RUN] Would install global: ${globalPkgs.join(' ')}`)\n }\n if (localPkgs.length > 0) {\n console.log(`[DRY RUN] Would install local deps: ${localPkgs.join(' ')}`)\n }\n if (devPkgs.length > 0) {\n console.log(`[DRY RUN] Would install dev deps: ${devPkgs.join(' ')}`)\n }\n return\n }\n\n if (globalPkgs.length > 0) {\n await npmRateLimiter.throttle()\n await execFileAsync('npm', ['i', '-g', ...globalPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 })\n }\n\n if (localPkgs.length > 0) {\n await npmRateLimiter.throttle()\n await execFileAsync('npm', ['i', ...localPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 })\n }\n\n if (devPkgs.length > 0) {\n await npmRateLimiter.throttle()\n await execFileAsync('npm', ['i', '-D', ...devPkgs], { cwd, maxBuffer: 10 * 1024 * 1024 })\n }\n}\n\n/**\n * Parses a report file (JSON or Markdown) and returns a Report object\n *\n * @param filePath Path to the report file\n * @returns Promise that resolves to a parsed Report object\n * @throws {ValidationError} If file path is invalid\n * @throws {Error} If file cannot be read or parsed\n *\n * @example\n * ```typescript\n * import { parseReportFile } from '@yabasha/gex'\n *\n * // Parse JSON report\n * const jsonReport = await parseReportFile('./gex-report.json')\n *\n * // Parse Markdown report\n * const mdReport = await parseReportFile('./gex-report.md')\n * ```\n */\nexport async function parseReportFile(filePath: string): Promise<Report> {\n const validatedPath = validateFilePath(filePath)\n const raw = await readFile(validatedPath, 'utf8')\n\n if (\n validatedPath.endsWith('.md') ||\n validatedPath.endsWith('.markdown') ||\n raw.startsWith('# GEX Report')\n ) {\n return parseMarkdownReport(raw)\n }\n\n try {\n return JSON.parse(raw) as Report\n } catch (error) {\n throw new Error(\n `Failed to parse report file as JSON: ${error instanceof Error ? error.message : 'Unknown error'}`,\n )\n }\n}\n\n/**\n * Gets the current tool version from package.json\n */\nasync function getToolVersion(): Promise<string> {\n try {\n const pkgPath = getPackageJsonPath()\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 * Gets the path to package.json\n */\nfunction getPackageJsonPath(): string {\n try {\n const __filename = import.meta.url.replace('file://', '')\n const __dirname = path.dirname(__filename)\n return path.resolve(__dirname, '..', 'package.json')\n } catch {\n return path.resolve(process.cwd(), 'package.json')\n }\n}\n\n/**\n * Parses a markdown report and converts it to a Report object\n * (Simplified version of CLI implementation)\n */\nfunction 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\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 return {\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}\n\n/**\n * Parses a markdown table and extracts 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) {\n rows.push({ name, version, resolved_path })\n }\n i++\n }\n\n return rows\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 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","import path from 'node:path'\nimport { setTimeout } from 'node:timers'\n\nimport type { OutputFormat } from './types.js'\n\n/**\n * Custom error class for validation failures\n */\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'ValidationError'\n }\n}\n\n/**\n * Validates and sanitizes file paths to prevent directory traversal attacks\n */\nexport function validateFilePath(filePath: string): string {\n if (!filePath || typeof filePath !== 'string') {\n throw new ValidationError('File path must be a non-empty string')\n }\n\n if (filePath.trim().length === 0) {\n throw new ValidationError('File path cannot be empty or whitespace only')\n }\n\n const suspiciousPatterns = [\n /\\.\\.\\//g, // Parent directory references\n /\\.\\.\\\\+/g, // Windows parent directory references\n /%2e%2e%2f/gi, // URL-encoded parent directory references\n /%2e%2e%5c/gi, // URL-encoded Windows parent directory references\n /\\0/g, // Null bytes\n ]\n\n for (const pattern of suspiciousPatterns) {\n if (pattern.test(filePath)) {\n throw new ValidationError('File path contains suspicious characters or patterns')\n }\n }\n\n const resolvedPath = path.resolve(filePath)\n const cwd = process.cwd()\n\n if (!resolvedPath.startsWith(cwd) && !path.isAbsolute(filePath)) {\n throw new ValidationError('File path attempts to access files outside the current directory')\n }\n\n return resolvedPath\n}\n\n/**\n * Validates output format\n */\nexport function validateOutputFormat(format: unknown): OutputFormat {\n if (format !== 'json' && format !== 'md') {\n throw new ValidationError('Output format must be \"json\" or \"md\"')\n }\n return format\n}\n\n/**\n * Validates and sanitizes package names\n */\nexport function validatePackageName(name: string): string {\n if (!name || typeof name !== 'string') {\n throw new ValidationError('Package name must be a non-empty string')\n }\n\n const trimmed = name.trim()\n if (trimmed.length === 0) {\n throw new ValidationError('Package name cannot be empty or whitespace only')\n }\n\n const packageNamePattern = /^(@[a-z0-9-_]+\\/)?[a-z0-9-_.]+$/i\n if (!packageNamePattern.test(trimmed)) {\n throw new ValidationError('Package name contains invalid characters')\n }\n\n if (trimmed.length > 214) {\n throw new ValidationError('Package name is too long')\n }\n\n return trimmed\n}\n\n/**\n * Validates semantic version strings\n */\nexport function validateVersion(version: string): string {\n if (typeof version !== 'string') {\n throw new ValidationError('Version must be a string')\n }\n\n const trimmed = version.trim()\n if (trimmed.length === 0) {\n return '' // Allow empty versions for broken packages\n }\n\n const semverPattern = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([a-zA-Z0-9-_.]+))?(?:\\+([a-zA-Z0-9-_.]+))?$/\n const relaxedPattern = /^[a-zA-Z0-9-_.+]+$/ // More permissive for npm's various formats\n\n if (!semverPattern.test(trimmed) && !relaxedPattern.test(trimmed)) {\n throw new ValidationError('Version contains invalid characters')\n }\n\n if (trimmed.length > 50) {\n throw new ValidationError('Version string is too long')\n }\n\n return trimmed\n}\n\n/**\n * Sanitizes text for safe inclusion in markdown tables\n */\nexport function sanitizeForMarkdown(text: string): string {\n if (!text || typeof text !== 'string') {\n return ''\n }\n\n return text\n .replace(/\\|/g, '\\\\|') // Escape pipe characters that could break table formatting\n .replace(/\\n/g, ' ') // Replace newlines with spaces\n .replace(/\\r/g, '') // Remove carriage returns\n .replace(/\\t/g, ' ') // Replace tabs with spaces\n .trim()\n}\n\n/**\n * Validates command options object\n */\nexport function validateCommandOptions(options: Record<string, unknown>): Record<string, unknown> {\n if (!options || typeof options !== 'object') {\n throw new ValidationError('Options must be an object')\n }\n\n const validatedOptions: Record<string, unknown> = {}\n\n if ('outputFormat' in options) {\n validatedOptions.outputFormat = validateOutputFormat(options.outputFormat)\n }\n\n if ('outFile' in options && options.outFile != null) {\n validatedOptions.outFile = validateFilePath(options.outFile as string)\n }\n\n if ('cwd' in options && options.cwd != null) {\n validatedOptions.cwd = validateFilePath(options.cwd as string)\n }\n\n for (const [key, value] of Object.entries(options)) {\n if (!Object.hasOwn(validatedOptions, key)) {\n if (typeof value === 'boolean' || typeof value === 'number' || typeof value === 'string') {\n validatedOptions[key] = value\n }\n }\n }\n\n return validatedOptions\n}\n\n/**\n * Rate limiting utility for npm operations\n */\nexport class RateLimiter {\n private lastCall: number = 0\n private readonly minInterval: number\n\n constructor(minIntervalMs: number = 100) {\n this.minInterval = minIntervalMs\n }\n\n /**\n * Ensures minimum time between operations\n */\n async throttle(): Promise<void> {\n const now = Date.now()\n const elapsed = now - this.lastCall\n\n if (elapsed < this.minInterval) {\n const delay = this.minInterval - elapsed\n await new Promise<void>((resolve) => setTimeout(resolve, delay))\n }\n\n this.lastCall = Date.now()\n }\n}\n\n/**\n * Global rate limiter instance for npm operations\n */\nexport const npmRateLimiter = new RateLimiter(50) // 50ms minimum between npm calls\n"],"mappings":"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","names":["import_promises","import_node_path","execFile","promisify","execFileAsync","path","import_node_path","path","path"]}
package/dist/index.d.cts CHANGED
@@ -1,7 +1,192 @@
1
1
  /**
2
- * Library API entry.
3
- * Export functions here for consumers who import your package.
2
+ * @fileoverview TypeScript type definitions for GEX dependency reporting
4
3
  */
5
- declare function greet(name: string): string;
4
+ /**
5
+ * Information about a single package/dependency
6
+ */
7
+ type PackageInfo = {
8
+ /** Package name (e.g., 'axios', '@types/node') */
9
+ name: string;
10
+ /** Package version (e.g., '1.6.0', '^18.0.0') */
11
+ version: string;
12
+ /** Resolved file system path to the package */
13
+ resolved_path: string;
14
+ };
15
+ /**
16
+ * Complete dependency report structure
17
+ */
18
+ type Report = {
19
+ /** Report format version for compatibility */
20
+ report_version: string;
21
+ /** ISO timestamp when report was generated */
22
+ timestamp: string;
23
+ /** Version of GEX tool that generated the report */
24
+ tool_version: string;
25
+ /** Optional project name from package.json */
26
+ project_name?: string;
27
+ /** Optional project version from package.json */
28
+ project_version?: string;
29
+ /** List of globally installed packages */
30
+ global_packages: PackageInfo[];
31
+ /** List of local production dependencies */
32
+ local_dependencies: PackageInfo[];
33
+ /** List of local development dependencies */
34
+ local_dev_dependencies: PackageInfo[];
35
+ /** Optional raw npm ls tree data */
36
+ tree?: unknown;
37
+ };
38
+ /**
39
+ * Supported output formats for reports
40
+ */
41
+ type OutputFormat = 'json' | 'md';
42
+
43
+ /**
44
+ * Custom error class for validation failures
45
+ */
46
+ declare class ValidationError extends Error {
47
+ constructor(message: string);
48
+ }
49
+
50
+ /**
51
+ * @fileoverview Library API for GEX - Node.js dependency auditing and reporting tool
52
+ * @version 0.3.2
53
+ */
54
+
55
+ /**
56
+ * Options for generating local dependency reports
57
+ */
58
+ interface LocalReportOptions {
59
+ /** Current working directory (defaults to process.cwd()) */
60
+ cwd?: string;
61
+ /** Whether to exclude devDependencies */
62
+ omitDev?: boolean;
63
+ /** Whether to use depth=0 for faster execution */
64
+ depth0?: boolean;
65
+ /** Whether to include the full npm ls tree in the report */
66
+ includeTree?: boolean;
67
+ /** Tool version to include in report metadata */
68
+ toolVersion?: string;
69
+ }
70
+ /**
71
+ * Options for generating global dependency reports
72
+ */
73
+ interface GlobalReportOptions {
74
+ /** Whether to use depth=0 for faster execution */
75
+ depth0?: boolean;
76
+ /** Whether to include the full npm ls tree in the report */
77
+ includeTree?: boolean;
78
+ /** Tool version to include in report metadata */
79
+ toolVersion?: string;
80
+ }
81
+ /**
82
+ * Options for installing packages from a report
83
+ */
84
+ interface InstallOptions {
85
+ /** Current working directory (defaults to process.cwd()) */
86
+ cwd?: string;
87
+ /** Whether to perform a dry run (log commands without executing) */
88
+ dryRun?: boolean;
89
+ }
90
+ /**
91
+ * Generates a dependency report for the local project
92
+ *
93
+ * @param options Configuration options for the report generation
94
+ * @returns Promise that resolves to a Report object
95
+ * @throws {ValidationError} If options are invalid
96
+ * @throws {Error} If npm operations fail
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * import { generateLocalReport } from '@yabasha/gex'
101
+ *
102
+ * const report = await generateLocalReport({
103
+ * omitDev: true,
104
+ * depth0: true
105
+ * })
106
+ *
107
+ * console.log(`Found ${report.local_dependencies.length} dependencies`)
108
+ * ```
109
+ */
110
+ declare function generateLocalReport(options?: LocalReportOptions): Promise<Report>;
111
+ /**
112
+ * Generates a dependency report for globally installed packages
113
+ *
114
+ * @param options Configuration options for the report generation
115
+ * @returns Promise that resolves to a Report object
116
+ * @throws {ValidationError} If options are invalid
117
+ * @throws {Error} If npm operations fail
118
+ *
119
+ * @example
120
+ * ```typescript
121
+ * import { generateGlobalReport } from '@yabasha/gex'
122
+ *
123
+ * const report = await generateGlobalReport({ depth0: true })
124
+ * console.log(`Found ${report.global_packages.length} global packages`)
125
+ * ```
126
+ */
127
+ declare function generateGlobalReport(options?: GlobalReportOptions): Promise<Report>;
128
+ /**
129
+ * Formats a report object as a string in the specified format
130
+ *
131
+ * @param report The report object to format
132
+ * @param format The output format ('json' or 'md')
133
+ * @param markdownExtras Additional metadata for markdown formatting
134
+ * @returns Formatted report as a string
135
+ * @throws {ValidationError} If format is invalid
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * import { generateLocalReport, formatReport } from '@yabasha/gex'
140
+ *
141
+ * const report = await generateLocalReport()
142
+ * const jsonOutput = formatReport(report, 'json')
143
+ * const markdownOutput = formatReport(report, 'md', {
144
+ * project_description: 'My awesome project'
145
+ * })
146
+ * ```
147
+ */
148
+ declare function formatReport(report: Report, format: OutputFormat, markdownExtras?: {
149
+ project_description?: string;
150
+ project_homepage?: string;
151
+ project_bugs?: string;
152
+ }): string;
153
+ /**
154
+ * Installs packages listed in a report
155
+ *
156
+ * @param report The report containing packages to install
157
+ * @param options Installation options
158
+ * @returns Promise that resolves when installation is complete
159
+ * @throws {ValidationError} If options are invalid
160
+ * @throws {Error} If npm installation fails
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * import { parseReportFile, installPackagesFromReport } from '@yabasha/gex'
165
+ *
166
+ * const report = await parseReportFile('./gex-report.json')
167
+ * await installPackagesFromReport(report, { dryRun: true })
168
+ * ```
169
+ */
170
+ declare function installPackagesFromReport(report: Report, options?: InstallOptions): Promise<void>;
171
+ /**
172
+ * Parses a report file (JSON or Markdown) and returns a Report object
173
+ *
174
+ * @param filePath Path to the report file
175
+ * @returns Promise that resolves to a parsed Report object
176
+ * @throws {ValidationError} If file path is invalid
177
+ * @throws {Error} If file cannot be read or parsed
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * import { parseReportFile } from '@yabasha/gex'
182
+ *
183
+ * // Parse JSON report
184
+ * const jsonReport = await parseReportFile('./gex-report.json')
185
+ *
186
+ * // Parse Markdown report
187
+ * const mdReport = await parseReportFile('./gex-report.md')
188
+ * ```
189
+ */
190
+ declare function parseReportFile(filePath: string): Promise<Report>;
6
191
 
7
- export { greet };
192
+ export { type GlobalReportOptions, type InstallOptions, type LocalReportOptions, type OutputFormat, type PackageInfo, type Report, ValidationError, formatReport, generateGlobalReport, generateLocalReport, installPackagesFromReport, parseReportFile };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,192 @@
1
1
  /**
2
- * Library API entry.
3
- * Export functions here for consumers who import your package.
2
+ * @fileoverview TypeScript type definitions for GEX dependency reporting
4
3
  */
5
- declare function greet(name: string): string;
4
+ /**
5
+ * Information about a single package/dependency
6
+ */
7
+ type PackageInfo = {
8
+ /** Package name (e.g., 'axios', '@types/node') */
9
+ name: string;
10
+ /** Package version (e.g., '1.6.0', '^18.0.0') */
11
+ version: string;
12
+ /** Resolved file system path to the package */
13
+ resolved_path: string;
14
+ };
15
+ /**
16
+ * Complete dependency report structure
17
+ */
18
+ type Report = {
19
+ /** Report format version for compatibility */
20
+ report_version: string;
21
+ /** ISO timestamp when report was generated */
22
+ timestamp: string;
23
+ /** Version of GEX tool that generated the report */
24
+ tool_version: string;
25
+ /** Optional project name from package.json */
26
+ project_name?: string;
27
+ /** Optional project version from package.json */
28
+ project_version?: string;
29
+ /** List of globally installed packages */
30
+ global_packages: PackageInfo[];
31
+ /** List of local production dependencies */
32
+ local_dependencies: PackageInfo[];
33
+ /** List of local development dependencies */
34
+ local_dev_dependencies: PackageInfo[];
35
+ /** Optional raw npm ls tree data */
36
+ tree?: unknown;
37
+ };
38
+ /**
39
+ * Supported output formats for reports
40
+ */
41
+ type OutputFormat = 'json' | 'md';
42
+
43
+ /**
44
+ * Custom error class for validation failures
45
+ */
46
+ declare class ValidationError extends Error {
47
+ constructor(message: string);
48
+ }
49
+
50
+ /**
51
+ * @fileoverview Library API for GEX - Node.js dependency auditing and reporting tool
52
+ * @version 0.3.2
53
+ */
54
+
55
+ /**
56
+ * Options for generating local dependency reports
57
+ */
58
+ interface LocalReportOptions {
59
+ /** Current working directory (defaults to process.cwd()) */
60
+ cwd?: string;
61
+ /** Whether to exclude devDependencies */
62
+ omitDev?: boolean;
63
+ /** Whether to use depth=0 for faster execution */
64
+ depth0?: boolean;
65
+ /** Whether to include the full npm ls tree in the report */
66
+ includeTree?: boolean;
67
+ /** Tool version to include in report metadata */
68
+ toolVersion?: string;
69
+ }
70
+ /**
71
+ * Options for generating global dependency reports
72
+ */
73
+ interface GlobalReportOptions {
74
+ /** Whether to use depth=0 for faster execution */
75
+ depth0?: boolean;
76
+ /** Whether to include the full npm ls tree in the report */
77
+ includeTree?: boolean;
78
+ /** Tool version to include in report metadata */
79
+ toolVersion?: string;
80
+ }
81
+ /**
82
+ * Options for installing packages from a report
83
+ */
84
+ interface InstallOptions {
85
+ /** Current working directory (defaults to process.cwd()) */
86
+ cwd?: string;
87
+ /** Whether to perform a dry run (log commands without executing) */
88
+ dryRun?: boolean;
89
+ }
90
+ /**
91
+ * Generates a dependency report for the local project
92
+ *
93
+ * @param options Configuration options for the report generation
94
+ * @returns Promise that resolves to a Report object
95
+ * @throws {ValidationError} If options are invalid
96
+ * @throws {Error} If npm operations fail
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * import { generateLocalReport } from '@yabasha/gex'
101
+ *
102
+ * const report = await generateLocalReport({
103
+ * omitDev: true,
104
+ * depth0: true
105
+ * })
106
+ *
107
+ * console.log(`Found ${report.local_dependencies.length} dependencies`)
108
+ * ```
109
+ */
110
+ declare function generateLocalReport(options?: LocalReportOptions): Promise<Report>;
111
+ /**
112
+ * Generates a dependency report for globally installed packages
113
+ *
114
+ * @param options Configuration options for the report generation
115
+ * @returns Promise that resolves to a Report object
116
+ * @throws {ValidationError} If options are invalid
117
+ * @throws {Error} If npm operations fail
118
+ *
119
+ * @example
120
+ * ```typescript
121
+ * import { generateGlobalReport } from '@yabasha/gex'
122
+ *
123
+ * const report = await generateGlobalReport({ depth0: true })
124
+ * console.log(`Found ${report.global_packages.length} global packages`)
125
+ * ```
126
+ */
127
+ declare function generateGlobalReport(options?: GlobalReportOptions): Promise<Report>;
128
+ /**
129
+ * Formats a report object as a string in the specified format
130
+ *
131
+ * @param report The report object to format
132
+ * @param format The output format ('json' or 'md')
133
+ * @param markdownExtras Additional metadata for markdown formatting
134
+ * @returns Formatted report as a string
135
+ * @throws {ValidationError} If format is invalid
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * import { generateLocalReport, formatReport } from '@yabasha/gex'
140
+ *
141
+ * const report = await generateLocalReport()
142
+ * const jsonOutput = formatReport(report, 'json')
143
+ * const markdownOutput = formatReport(report, 'md', {
144
+ * project_description: 'My awesome project'
145
+ * })
146
+ * ```
147
+ */
148
+ declare function formatReport(report: Report, format: OutputFormat, markdownExtras?: {
149
+ project_description?: string;
150
+ project_homepage?: string;
151
+ project_bugs?: string;
152
+ }): string;
153
+ /**
154
+ * Installs packages listed in a report
155
+ *
156
+ * @param report The report containing packages to install
157
+ * @param options Installation options
158
+ * @returns Promise that resolves when installation is complete
159
+ * @throws {ValidationError} If options are invalid
160
+ * @throws {Error} If npm installation fails
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * import { parseReportFile, installPackagesFromReport } from '@yabasha/gex'
165
+ *
166
+ * const report = await parseReportFile('./gex-report.json')
167
+ * await installPackagesFromReport(report, { dryRun: true })
168
+ * ```
169
+ */
170
+ declare function installPackagesFromReport(report: Report, options?: InstallOptions): Promise<void>;
171
+ /**
172
+ * Parses a report file (JSON or Markdown) and returns a Report object
173
+ *
174
+ * @param filePath Path to the report file
175
+ * @returns Promise that resolves to a parsed Report object
176
+ * @throws {ValidationError} If file path is invalid
177
+ * @throws {Error} If file cannot be read or parsed
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * import { parseReportFile } from '@yabasha/gex'
182
+ *
183
+ * // Parse JSON report
184
+ * const jsonReport = await parseReportFile('./gex-report.json')
185
+ *
186
+ * // Parse Markdown report
187
+ * const mdReport = await parseReportFile('./gex-report.md')
188
+ * ```
189
+ */
190
+ declare function parseReportFile(filePath: string): Promise<Report>;
6
191
 
7
- export { greet };
192
+ export { type GlobalReportOptions, type InstallOptions, type LocalReportOptions, type OutputFormat, type PackageInfo, type Report, ValidationError, formatReport, generateGlobalReport, generateLocalReport, installPackagesFromReport, parseReportFile };