UNPKG

@bomb.sh/tools

Version:

The internal dev, build, and lint CLI for Bombshell projects

1 lines 19.9 kB
{"version":3,"file":"lint.mjs","names":[],"sources":["../../src/commands/lint.ts"],"sourcesContent":["import { fileURLToPath } from 'node:url';\nimport { readFile, rm, writeFile } from 'node:fs/promises';\nimport { parse } from '@bomb.sh/args';\nimport { x } from 'tinyexec';\nimport type { JSONReport as KnipJSONReport } from 'knip';\nimport type { CommandContext } from '../context.ts';\nimport { getPublicSurface } from '../surface.ts';\nimport { local, ToolsError } from '../utils.ts';\n\nconst oxlintConfig = fileURLToPath(new URL('../../oxlintrc.json', import.meta.url));\n\n/**\n * Rules that only apply to the public API surface (see `surface.ts`).\n * Moved from the global ruleset into `overrides` at runtime.\n */\nconst SURFACE_RULES = [\n\t'bombshell-dev/exported-function-async',\n\t'bombshell-dev/require-export-jsdoc',\n];\n\n/**\n * Generate the effective oxlint config for the project at `cwd`.\n *\n * Surface-scoped rules are lifted out of the shared config's global ruleset\n * and re-applied via `overrides` limited to the package's public API surface,\n * so internal modules aren't held to public-API conventions. Written into the\n * project root because oxlint resolves `overrides.files` relative to the\n * config location; deleted after the run.\n */\nasync function withEffectiveConfig<T>(run: (configPath: string) => Promise<T>): Promise<T> {\n\tconst cwd = process.cwd();\n\tconst base = JSON.parse(await readFile(oxlintConfig, 'utf-8'));\n\tdelete base.$schema;\n\n\t// jsPlugins paths are relative to the shared config — make them absolute\n\t// so the generated copy can live anywhere.\n\tif (Array.isArray(base.jsPlugins)) {\n\t\tbase.jsPlugins = base.jsPlugins.map((plugin: string) =>\n\t\t\tfileURLToPath(new URL(plugin, new URL('../../oxlintrc.json', import.meta.url))),\n\t\t);\n\t}\n\n\tconst surface = await getPublicSurface(new URL(`file://${cwd}/`));\n\tconst scoped: Record<string, unknown> = {};\n\tfor (const rule of SURFACE_RULES) {\n\t\tif (base.rules?.[rule] !== undefined) {\n\t\t\tscoped[rule] = base.rules[rule];\n\t\t\tdelete base.rules[rule];\n\t\t}\n\t}\n\tif (surface.length > 0 && Object.keys(scoped).length > 0) {\n\t\tbase.overrides = [...(base.overrides ?? []), { files: surface, rules: scoped }];\n\t}\n\n\tconst configPath = `${cwd}/.bsh.oxlintrc.json`;\n\tawait writeFile(configPath, JSON.stringify(base, null, 2));\n\ttry {\n\t\treturn await run(configPath);\n\t} finally {\n\t\tawait rm(configPath, { force: true });\n\t}\n}\n\n// -- Types --\n\ninterface Violation {\n\ttool: 'oxlint' | 'publint' | 'knip' | 'tsc';\n\tlevel: 'error' | 'warning' | 'suggestion';\n\tcode: string;\n\tmessage: string;\n\tfile?: string;\n\tline?: number;\n\tcolumn?: number;\n}\n\n// -- Tool Runners --\n\nexport async function runOxlint(targets: string[], fix?: boolean): Promise<Violation[]> {\n\treturn withEffectiveConfig(async (config) => {\n\t\tconst args = ['-c', config, '--format=json', ...targets];\n\t\tif (fix) args.push('--fix');\n\t\tconst result = await x(local('oxlint'), args, { throwOnError: false });\n\t\ttry {\n\t\t\tconst json = JSON.parse(result.stdout);\n\t\t\treturn (json.diagnostics ?? []).map(\n\t\t\t\t(d: {\n\t\t\t\t\tmessage: string;\n\t\t\t\t\tcode: string;\n\t\t\t\t\tseverity: string;\n\t\t\t\t\tfilename?: string;\n\t\t\t\t\tlabels?: Array<{ span?: { line?: number; column?: number } }>;\n\t\t\t\t}) => ({\n\t\t\t\t\ttool: 'oxlint' as const,\n\t\t\t\t\tlevel: d.severity === 'error' ? 'error' : 'warning',\n\t\t\t\t\tcode: d.code ?? 'unknown',\n\t\t\t\t\tmessage: d.message,\n\t\t\t\t\tfile: d.filename,\n\t\t\t\t\tline: d.labels?.[0]?.span?.line,\n\t\t\t\t\tcolumn: d.labels?.[0]?.span?.column,\n\t\t\t\t}),\n\t\t\t);\n\t\t} catch {\n\t\t\tif (result.exitCode !== 0)\n\t\t\t\tthrow new ToolsError(`oxlint exited with code ${result.exitCode}`, 'oxlint-exit');\n\t\t\t// no-ops do not produce valid JSON — fall back to raw output\n\t\t\tconsole.info(result.stdout);\n\t\t\treturn [];\n\t\t}\n\t});\n}\n\n/**\n * Mechanically fix knip-reported issues. Dependency hygiene (removing unused\n * deps from package.json) always runs with `--fix`; dead-code fixes (unused\n * exports/types) only run in `--strict` mode, matching the report tiers.\n * Unused files are never deleted automatically.\n */\nexport async function runKnipFix(strict?: boolean): Promise<void> {\n\tconst types = strict ? 'dependencies,exports,types' : 'dependencies';\n\tawait x(local('knip'), ['--fix', '--fix-type', types, '--no-progress'], {\n\t\tthrowOnError: false,\n\t});\n}\n\n/**\n * Knip dead-code issue kinds (unused exports/types/files) fire constantly\n * mid-implementation — an export is \"unused\" until its consumer exists.\n * They only carry signal as a commit-time gate, so they require `--strict`.\n * Dependency hygiene issues are stable and always reported.\n */\nexport async function runKnip(options?: { strict?: boolean }): Promise<Violation[]> {\n\tconst args = ['--no-progress', '--reporter', 'json'];\n\tconst result = await x(local('knip'), args, { throwOnError: false });\n\tif (!result.stdout.trim()) return [];\n\n\tlet json: KnipJSONReport;\n\ttry {\n\t\tjson = JSON.parse(result.stdout);\n\t} catch {\n\t\tif (result.exitCode !== 0)\n\t\t\tthrow new ToolsError(`knip exited with code ${result.exitCode}`, 'knip-exit');\n\t\treturn [];\n\t}\n\tconst violations: Violation[] = [];\n\n\tfor (const issue of json.issues) {\n\t\tfor (const dep of issue.dependencies ?? []) {\n\t\t\tviolations.push({\n\t\t\t\ttool: 'knip',\n\t\t\t\tlevel: 'warning',\n\t\t\t\tcode: 'unused-dependency',\n\t\t\t\tmessage: `Unused dependency '${dep.name}'`,\n\t\t\t\tfile: issue.file,\n\t\t\t\tline: dep.line,\n\t\t\t\tcolumn: dep.col,\n\t\t\t});\n\t\t}\n\t\tfor (const dep of issue.devDependencies ?? []) {\n\t\t\tviolations.push({\n\t\t\t\ttool: 'knip',\n\t\t\t\tlevel: 'warning',\n\t\t\t\tcode: 'unused-devDependency',\n\t\t\t\tmessage: `Unused devDependency '${dep.name}'`,\n\t\t\t\tfile: issue.file,\n\t\t\t\tline: dep.line,\n\t\t\t\tcolumn: dep.col,\n\t\t\t});\n\t\t}\n\t\tif (!options?.strict) continue;\n\t\tfor (const exp of issue.exports ?? []) {\n\t\t\tviolations.push({\n\t\t\t\ttool: 'knip',\n\t\t\t\tlevel: 'warning',\n\t\t\t\tcode: 'unused-export',\n\t\t\t\tmessage: `Unused export '${exp.name}'`,\n\t\t\t\tfile: issue.file,\n\t\t\t\tline: exp.line,\n\t\t\t\tcolumn: exp.col,\n\t\t\t});\n\t\t}\n\t\tfor (const t of issue.types ?? []) {\n\t\t\tviolations.push({\n\t\t\t\ttool: 'knip',\n\t\t\t\tlevel: 'warning',\n\t\t\t\tcode: 'unused-type',\n\t\t\t\tmessage: `Unused type '${t.name}'`,\n\t\t\t\tfile: issue.file,\n\t\t\t\tline: t.line,\n\t\t\t\tcolumn: t.col,\n\t\t\t});\n\t\t}\n\t\tfor (const file of issue.files ?? []) {\n\t\t\tviolations.push({\n\t\t\t\ttool: 'knip',\n\t\t\t\tlevel: 'warning',\n\t\t\t\tcode: 'unused-file',\n\t\t\t\tmessage: `Unused file`,\n\t\t\t\tfile: issue.file,\n\t\t\t\tline: file.line,\n\t\t\t\tcolumn: file.col,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn violations;\n}\n\nasync function runTypeScript(targets: string[]): Promise<Violation[]> {\n\t// Always run in project mode: passing files on the command line makes\n\t// tsgo skip the tsconfig (TS5112). Explicit targets filter the report\n\t// after the fact instead.\n\tconst result = await x(local('tsgo'), ['--noEmit', '--pretty', 'false'], {\n\t\tthrowOnError: false,\n\t});\n\tconst output = result.stdout + result.stderr;\n\tif (!output.trim()) {\n\t\tif (result.exitCode !== 0)\n\t\t\tthrow new ToolsError(`tsgo exited with code ${result.exitCode}`, 'tsgo-exit');\n\t\treturn [];\n\t}\n\n\tconst violations: Violation[] = [];\n\tconst re = /^(.+)\\((\\d+),(\\d+)\\): (error|warning) (TS\\d+): (.+)$/gm;\n\tlet match: RegExpExecArray | null;\n\twhile ((match = re.exec(output)) !== null) {\n\t\tviolations.push({\n\t\t\ttool: 'tsc',\n\t\t\tlevel: match[4] === 'error' ? 'error' : 'warning',\n\t\t\tcode: match[5]!,\n\t\t\tmessage: match[6]!,\n\t\t\tfile: match[1]!,\n\t\t\tline: Number(match[2]),\n\t\t\tcolumn: Number(match[3]),\n\t\t});\n\t}\n\tif (targets.length === 0) return violations;\n\tconst prefixes = targets.map((t) => t.replace(/^\\.\\//, ''));\n\treturn violations.filter((v) => v.file && prefixes.some((p) => v.file!.startsWith(p)));\n}\n\n// -- Output --\n\nconst colors = {\n\terror: '\\x1b[31m',\n\twarning: '\\x1b[33m',\n\tsuggestion: '\\x1b[34m',\n\tdim: '\\x1b[2m',\n\treset: '\\x1b[0m',\n};\n\nfunction printViolation(v: Violation) {\n\tconst loc = v.line != null ? ` ${v.line}:${v.column ?? 0}` : ' -';\n\tconst color = colors[v.level];\n\tconst tag = `${v.tool}/${v.code}`;\n\tconsole.log(\n\t\t`${colors.dim}${loc.padEnd(10)}${colors.reset}${color}${v.level.padEnd(12)}${colors.reset}${v.message} ${colors.dim}${tag}${colors.reset}`,\n\t);\n}\n\nfunction countByLevel(violations: Violation[]) {\n\tconst counts = { error: 0, warning: 0, suggestion: 0 };\n\tfor (const v of violations) counts[v.level]++;\n\treturn counts;\n}\n\nfunction printSummary(violations: Violation[]) {\n\tconst counts = countByLevel(violations);\n\tconst parts = [];\n\tif (counts.error)\n\t\tparts.push(`${colors.error}${counts.error} error${counts.error > 1 ? 's' : ''}${colors.reset}`);\n\tif (counts.warning)\n\t\tparts.push(\n\t\t\t`${colors.warning}${counts.warning} warning${counts.warning > 1 ? 's' : ''}${colors.reset}`,\n\t\t);\n\tif (counts.suggestion)\n\t\tparts.push(\n\t\t\t`${colors.suggestion}${counts.suggestion} suggestion${counts.suggestion > 1 ? 's' : ''}${colors.reset}`,\n\t\t);\n\tconsole.log(parts.length > 0 ? `\\n${parts.join(', ')}` : '\\nNo issues found.');\n}\n\n/**\n * Print violations grouped by file. Errors are always shown in full.\n * Warnings collapse to a per-rule count unless `warnings` is set — they\n * don't affect the exit code, so a wall of them buries actual failures.\n */\nexport function printViolations(violations: Violation[], options?: { warnings?: boolean }) {\n\tconst showWarnings = options?.warnings ?? false;\n\tconst visible = showWarnings ? violations : violations.filter((v) => v.level === 'error');\n\n\tconst grouped = new Map<string, Violation[]>();\n\tfor (const v of visible) {\n\t\tconst key = v.file ?? '(project)';\n\t\tif (!grouped.has(key)) grouped.set(key, []);\n\t\tgrouped.get(key)!.push(v);\n\t}\n\n\tfor (const [file, items] of grouped) {\n\t\tconsole.log(`\\n${file}`);\n\t\tfor (const v of items) printViolation(v);\n\t}\n\n\tif (!showWarnings) {\n\t\tconst hidden = violations.filter((v) => v.level !== 'error');\n\t\tif (hidden.length > 0) {\n\t\t\tconst byRule = new Map<string, number>();\n\t\t\tfor (const v of hidden) {\n\t\t\t\tconst tag = `${v.tool}/${v.code}`;\n\t\t\t\tbyRule.set(tag, (byRule.get(tag) ?? 0) + 1);\n\t\t\t}\n\t\t\tconsole.log(\n\t\t\t\t`\\n${colors.dim}${hidden.length} warning${hidden.length > 1 ? 's' : ''} hidden (run with --warnings to show):${colors.reset}`,\n\t\t\t);\n\t\t\tfor (const [tag, count] of [...byRule].sort((a, b) => b[1] - a[1])) {\n\t\t\t\tconsole.log(`${colors.dim} ${count} × ${tag}${colors.reset}`);\n\t\t\t}\n\t\t}\n\t}\n\n\tprintSummary(violations);\n}\n\n/** Machine-readable report for agents and CI. */\nexport function printJson(violations: Violation[]) {\n\tconsole.log(JSON.stringify({ summary: countByLevel(violations), violations }, null, 2));\n}\n\n// -- Main --\n\nasync function collectViolations(\n\ttargets: string[],\n\toptions?: { strict?: boolean },\n): Promise<{ violations: Violation[]; failed: boolean }> {\n\t// oxlint honors targets (default: project-wide); tsgo runs in project\n\t// mode unless the user explicitly narrowed the target set.\n\tconst explicit = targets.length > 0;\n\tconst results = await Promise.allSettled([\n\t\trunOxlint(explicit ? targets : ['.']),\n\t\trunKnip({ strict: options?.strict }),\n\t\trunTypeScript(explicit ? targets : []),\n\t]);\n\n\tconst violations: Violation[] = [];\n\tlet failed = false;\n\tfor (const result of results) {\n\t\tif (result.status === 'fulfilled') {\n\t\t\tviolations.push(...result.value);\n\t\t} else {\n\t\t\tfailed = true;\n\t\t\tconsole.error(result.reason);\n\t\t}\n\t}\n\treturn { violations, failed };\n}\n\nexport async function lint(ctx: CommandContext) {\n\tconst args = parse(ctx.args, {\n\t\tboolean: ['fix', 'strict', 'warnings'],\n\t\tstring: ['format'],\n\t});\n\tconst targets = args._.map(String);\n\tconst json = args.format === 'json';\n\tconst print = (violations: Violation[]) =>\n\t\tjson ? printJson(violations) : printViolations(violations, { warnings: args.warnings });\n\n\tif (args.fix) {\n\t\tawait runOxlint(targets.length > 0 ? targets : ['.'], true);\n\t\tawait runKnipFix(args.strict);\n\n\t\t// Report remaining\n\t\tconst { violations: remaining, failed } = await collectViolations(targets, {\n\t\t\tstrict: args.strict,\n\t\t});\n\t\tif (remaining.length > 0) {\n\t\t\tprint(remaining);\n\t\t\tif (remaining.some((v) => v.level === 'error') || failed) process.exit(1);\n\t\t\treturn;\n\t\t}\n\t\tif (failed) process.exit(1);\n\t\tif (!json) console.log('No issues found.');\n\t\treturn;\n\t}\n\n\t// Default: report only\n\tconst { violations, failed } = await collectViolations(targets, { strict: args.strict });\n\tprint(violations);\n\tif (violations.some((v) => v.level === 'error') || failed) {\n\t\tprocess.exit(1);\n\t}\n}\n"],"mappings":"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"}