lintTexts
uses node:fs
Lint texts (each with the extension it needs, .ts or .tsx) with one oxlint run: the issues of each.
import type { Codebase } from "#codebase/tcmts/cli/codebase"; import { configFor } from "#codebase/tcmts/cli/lint"; import type { LintIssue, LintTraits, OxlintDiagnostic } from "#codebase/tcmts/cli/lint"; import { spawnSync } from "node:child_process"; import fs from "node:fs"; import path from "node:path"; export function lintTexts( cb: Codebase, texts: { text: string; ext: string }[], traits: LintTraits, ): LintIssue[][] { if (!texts.length) return []; const { file: config, bin } = configFor(cb, traits); const dir = fs.mkdtempSync(path.join(cb.lay.tcmDir, "lint", "run-")); try { const files = texts.map((t, i) => { const f = path.join(dir, `${i}${t.ext}`); fs.writeFileSync(f, t.text); return f; }); const r = spawnSync( process.execPath, [bin, "--format=json", "-c", config, "--no-ignore", ...files], { encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }, ); let parsed: { diagnostics?: OxlintDiagnostic[] }; try { parsed = JSON.parse(r.stdout) as { diagnostics?: OxlintDiagnostic[] }; } catch { throw new Error(`oxlint failed: ${r.stderr || r.stdout}`); } const byFile = new Map(files.map((f) => [path.basename(f), [] as LintIssue[]])); for (const d of parsed.diagnostics ?? []) { const span = d.labels?.[0]?.span; byFile.get(path.basename(d.filename))?.push({ rule: d.code, message: d.message, severity: d.severity === "error" ? "error" : "warning", ...(d.help ? { help: d.help } : {}), ...(d.url ? { url: d.url } : {}), start: span?.offset ?? 0, end: (span?.offset ?? 0) + (span?.length ?? 0), }); } return files.map((f) => byFile.get(path.basename(f)) ?? []); } finally { fs.rmSync(dir, { recursive: true, force: true }); } }
uses
- tcmts.cli.codebase.Codebase
- tcmts.cli.lint.LintIssue
- tcmts.cli.lint.LintTraits
- tcmts.cli.lint.OxlintDiagnostic
- tcmts.cli.lint.configFor