@rnm/tscx
Version:
A tsc wrapper with many convenient features.
98 lines (87 loc) • 2.61 kB
text/typescript
// this file should not have `async` and `await`
import path from "node:path";
import process from "node:process";
import chokidar, { type FSWatcher } from "chokidar";
import { Compiler, type CompilerOptions } from "./compiler.ts";
interface TscxOptions extends CompilerOptions {
watch: boolean;
}
export class Action {
private lastUpdateTsconfigTime = Date.now();
private readonly compiler;
private watcher?: FSWatcher;
constructor(private readonly options: TscxOptions) {
const { watch, ...compilerOptions } = options;
this.compiler = new Compiler(compilerOptions);
}
private watch(paths: string[]) {
this.watcher = chokidar
.watch(paths, {
ignored: [
"**/node_modules/**",
"**/.git/**",
this.compiler.getOutDir(),
],
ignoreInitial: true,
})
.on("add", (filepath) => this.cb(filepath))
.on("unlink", (filepath) => this.cb(filepath))
.on("change", (filepath) => this.cb(filepath))
.on("ready", () => this.cb());
}
private setupWatcher() {
const include = this.compiler.getInclude() ?? [];
const watchFiles =
include.length <= 0
? [process.cwd()]
: include
.map((i) => path.resolve(process.cwd(), i))
.concat(path.resolve(process.cwd(), this.options.project));
if (this.watcher) {
// If this method throw an error (I mean the promise rejected), the process will exit with non-zero code.
// See https://github.com/zanminkian/zanminkian.github.io/issues/54
this.watcher.close().then(
() => this.watch(watchFiles),
(e) => {
throw new Error("Close watcher fail!", { cause: e });
},
);
} else {
this.watch(watchFiles);
}
}
private cb(filepath?: string) {
console.log("File changes detected", filepath);
// user edit non-tsconfig files
if (
!filepath ||
path.resolve(process.cwd(), filepath) !==
path.resolve(process.cwd(), this.options.project)
) {
return this.compiler.compile();
}
// user edit tsconfig file
const now = Date.now();
if (now - this.lastUpdateTsconfigTime < 1000) {
return;
}
try {
this.compiler.refreshTsConfig();
} catch (e) {
console.warn(
"Refresh ts config fail. You can ignore this small warning.",
e,
);
return;
}
this.setupWatcher();
this.lastUpdateTsconfigTime = now;
}
start() {
if (!this.options.watch) {
this.compiler.compile();
return;
}
this.setupWatcher();
}
}