UNPKG

git-contributor-stats

Version:

CLI to compute contributor and repository statistics from a Git repository (commits, lines added/deleted, frequency, heatmap, bus-factor), with filters and multiple output formats.

1 lines 8.71 kB
{"version":3,"file":"cli.mjs","sources":["../src/cli/options.ts","../src/cli/index.ts","../src/cli/entry.ts"],"sourcesContent":["import { Command } from 'commander';\n\nexport interface PackageJson {\n version?: string;\n [key: string]: unknown;\n}\n\nexport function setupCLI(pkg: PackageJson): Command {\n const program = new Command();\n\n program\n .name('git-contributor-stats')\n .description('Compute contributor and repository statistics from a Git repository')\n .version(pkg.version || '0.0.0')\n .argument('[paths...]', 'Optional pathspec(s) to limit stats to certain files or directories')\n .option('-r, --repo <repoPath>', 'Path to the Git repository (default: current directory)', '.')\n .option(\n '-b, --branch <name>',\n 'Branch or commit range to analyze (e.g., main or main..feature)'\n )\n .option(\n '--since <when>',\n \"Only include commits more recent than <when> (e.g., '2024-01-01', '30.days', '2.weeks')\"\n )\n .option('--until <when>', \"Only include commits older than <when> (e.g., '2024-06-30')\")\n .option(\n '-a, --author <pattern>',\n 'Limit to commits by author (string or regex supported by git)'\n )\n .option('--include-merges', 'Include merge commits (excluded by default)', false)\n .option('-g, --group-by <field>', 'Grouping key: email | name (default: email)', 'email')\n .option('-l, --label-by <field>', 'Display label: email | name (default: name)', 'name')\n .option(\n '-s, --sort-by <metric>',\n 'Sort by: changes | commits | additions | deletions',\n 'changes'\n )\n .option('-t, --top <n>', 'Limit to top N contributors (for table/CSV stdout)', (v: string) =>\n Number.parseInt(v, 10)\n )\n .option('-f, --format <kind>', 'Output format to stdout: table | json | csv', 'table')\n .option('--json', 'Print comprehensive JSON analysis to stdout', false)\n .option('--csv <csvPath>', 'Write CSV contributors summary to file')\n .option('--md <mdPath>', 'Write Markdown report to file')\n .option('--html <htmlPath>', 'Write HTML dashboard report to file')\n .option(\n '--out-dir <outDir>',\n 'Write selected outputs into the directory (uses default filenames)'\n )\n .option(\n '--charts',\n 'Generate charts (defaults to SVG). Use --chart-format to switch formats.',\n false\n )\n .option(\n '--charts-dir <chartsDir>',\n 'Directory to write charts (overrides default when --charts is set)'\n )\n .option(\n '--chart-format <format>',\n 'Chart output format: svg | png | both (default: svg)',\n 'svg'\n )\n .option(\n '--similarity <threshold>',\n 'Name merge similarity threshold (0..1)',\n (v: string) => Number.parseFloat(v),\n 0.85\n )\n .option('--alias-file <aliasFile>', 'Path to alias mapping JSON file')\n .option('--no-count-lines', 'Skip counting total lines in repo (faster)')\n .option('--no-top-stats', 'Omit the Top stats section in Markdown/HTML and stdout table output')\n .option(\n '--top-stats <list>',\n 'Top stats metrics to show (comma-separated): commits, additions, deletions, net, changes'\n )\n .option(\n '--generate-workflow',\n 'Create a sample GitHub Actions workflow under .github/workflows/',\n false\n )\n .option('-v, --verbose', 'Verbose logging', false)\n .addHelpText(\n 'after',\n `\\nExamples:\\n # Top 10 contributors in the current repo\\n git-contributor-stats --top 10\\n\\n # Only for the last 90 days on main\\n git-contributor-stats -b main --since 90.days\\n\\n # Stats for a specific folder, as JSON (comprehensive)\\n git-contributor-stats src/ --json\\n\\n # Generate Markdown and HTML reports into reports/ and write charts\\n git-contributor-stats --out-dir reports --md reports/report.md --html reports/report.html --charts\\n\\n # Merge similar contributor names (default threshold 0.85)\\n git-contributor-stats --similarity 0.9\\n`\n );\n\n return program;\n}\n","#!/usr/bin/env node\n\nimport path from 'node:path';\nimport process from 'node:process';\nimport { generateCharts } from '../features/charts.ts';\nimport { handleStdoutOutput } from '../features/output.ts';\nimport { generateReports } from '../features/reports.ts';\nimport { type ContributorStatsResult, getContributorStats } from '../features/stats.ts';\nimport { generateWorkflow } from '../features/workflow.ts';\nimport { isGitRepo } from '../git/utils.ts';\nimport { safeReadPackageJson } from '../utils/files.ts';\nimport { setupCLI } from './options.ts';\n\nasync function main(argv: string[]): Promise<void> {\n const pkg = safeReadPackageJson();\n const program = setupCLI(pkg);\n program.parse(argv);\n const opts = program.opts();\n const paths: string[] = program.args || [];\n\n const repo = path.resolve(process.cwd(), opts.repo || '.');\n if (!isGitRepo(repo)) {\n console.error(`Not a Git repository: ${repo}`);\n process.exit(2);\n }\n\n const apiOptions = {\n repo,\n branch: opts.branch,\n since: opts.since,\n until: opts.until,\n author: opts.author,\n includeMerges: !!opts.includeMerges,\n groupBy: opts.groupBy,\n labelBy: opts.labelBy,\n sortBy: opts.sortBy,\n top: opts.top,\n similarity: opts.similarity,\n aliasFile: opts.aliasFile,\n countLines: opts.countLines,\n paths,\n verbose: opts.verbose\n };\n\n let final: ContributorStatsResult;\n try {\n final = await getContributorStats(apiOptions);\n } catch (e) {\n console.error((e as Error)?.message || String(e));\n process.exit(2);\n }\n\n // Generate reports\n await generateReports(final, opts);\n\n // Generate charts\n await generateCharts(final, opts, opts.outDir);\n\n // Generate workflow if requested\n if (opts.generateWorkflow) {\n await generateWorkflow(repo);\n }\n\n // Handle stdout output\n handleStdoutOutput(final, {\n json: opts.json,\n format: opts.format,\n topStats: opts.topStats,\n labelBy: opts.labelBy\n });\n}\n\nexport { main };\n","#!/usr/bin/env node\nimport { main } from './index.ts';\n\ntry {\n await main(process.argv);\n} catch (err: unknown) {\n console.error(err instanceof Error ? err.stack : String(err));\n process.exit(2);\n}\n"],"names":["process"],"mappings":"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"}