Skip to content

Instantly share code, notes, and snippets.

@hasenj
Created November 10, 2024 11:03
Show Gist options
  • Save hasenj/2c61559b43ba284ba981bfd80c3ac0ba to your computer and use it in GitHub Desktop.
Save hasenj/2c61559b43ba284ba981bfd80c3ac0ba to your computer and use it in GitHub Desktop.
nodejs script to run a watch mode typescript checker that can optionally output to json for consumption by other programs
// Generated by Claude
// Some details hand tuned
import fs from 'fs'
import ts from 'typescript';
import path from 'path';
function getConfig() {
const args = process.argv.slice(2);
const jsonIndex = args.indexOf('--json');
const useJson = jsonIndex !== -1;
const paths = args.filter((arg, i) => !arg.startsWith('--') && i !== jsonIndex + 1);
if (paths.length === 0) {
paths.push('.');
}
const invalidPaths = paths.filter(p => !fs.existsSync(p));
if (invalidPaths.length > 0) {
console.error('Invalid paths:', invalidPaths.join(', '));
process.exit(1);
}
return { paths, useJson };
}
const { paths, useJson } = getConfig();
let cwd = process.cwd()
function watchProgram(rootFiles) {
const configPath = ts.findConfigFile(cwd, ts.sys.fileExists, "tsconfig.json");
if (!configPath) throw new Error("tsconfig.json not found");
const host = ts.createWatchCompilerHost(
configPath,
{ noEmit: true },
ts.sys,
ts.createSemanticDiagnosticsBuilderProgram,
reportDiagnostic,
reportWatchStatus,
);
ts.createWatchProgram(host);
}
function categoryLabel(category) {
switch (category) {
case 0: return "warning"
case 1: return "error"
case 2: return "suggestion"
case 3: return "message"
}
}
function reportDiagnostic(diagnostic) {
if (!diagnostic.file) return;
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
let category = categoryLabel(diagnostic.category)
let time = formatDate(new Date())
let fileName = path.relative(cwd, diagnostic.file.fileName)
if (diagnostic.category === 1) { // error
if (useJson) {
console.log(JSON.stringify({
time,
category,
fileName,
line: line+1,
character: character+1,
code: diagnostic.code,
message,
}))
} else {
console.log(`${time} ${category} TS${diagnostic.code} ${fileName}:${line+1}:${character+1}`);
console.log(message)
}
}
}
// Generated by Claude
function formatDate(date) {
const pad = n => n.toString().padStart(2, '0');
const year = date.getFullYear();
const month = pad(date.getMonth() + 1);
const day = pad(date.getDate());
const hour = pad(date.getHours());
const minute = pad(date.getMinutes());
const second = pad(date.getSeconds());
return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}
function reportWatchStatus(diagnostic) {
/*
if (useJson) {
console.log("{}")
} else {
console.log("----", formatDate(new Date()))
}
*/
}
watchProgram(paths);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment