-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fffe2e1
commit f3403a3
Showing
9 changed files
with
389 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@rnm/tscx": minor | ||
--- | ||
|
||
feat: init |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import path from "node:path"; | ||
import process from "node:process"; | ||
import chokidar, { type FSWatcher } from "chokidar"; | ||
import { Compiler, type CompilerOptions } from "./compiler.js"; | ||
|
||
interface TscxOptions extends CompilerOptions { | ||
watch: boolean; | ||
} | ||
|
||
export class Action { | ||
private readonly compiler; | ||
private watcher?: FSWatcher; | ||
constructor(private readonly options: TscxOptions) { | ||
this.compiler = new Compiler(options); | ||
} | ||
|
||
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)); | ||
|
||
this.watcher = chokidar.watch(watchFiles, { | ||
ignored: ["**/node_modules/**", "**/.git/**", this.compiler.getOutDir()], | ||
ignoreInitial: true, | ||
}); | ||
this.watcher | ||
.on("add", (filepath) => this.cb(filepath)) | ||
.on("unlink", (filepath) => this.cb(filepath)) | ||
.on("change", (filepath) => this.cb(filepath)) | ||
.on("ready", () => this.cb()); | ||
} | ||
|
||
private cb(filepath?: string) { | ||
console.log("Recompile for the file updated", filepath); | ||
if ( | ||
!filepath || | ||
path.resolve(process.cwd(), filepath) !== | ||
path.resolve(process.cwd(), this.options.project) | ||
) { | ||
return this.compiler.exec(); | ||
} | ||
|
||
this.compiler.refreshTsConfig(); | ||
this.watcher | ||
?.close() | ||
.then(() => { | ||
this.setupWatcher(); | ||
}) | ||
.catch((e) => { | ||
console.error("Close watcher fail!", e); | ||
process.exit(1); | ||
}); | ||
} | ||
|
||
start() { | ||
if (!this.options.watch) { | ||
this.compiler.exec(); | ||
return; | ||
} | ||
|
||
this.setupWatcher(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import fs from "node:fs/promises"; | ||
import path from "node:path"; | ||
import { fileURLToPath } from "node:url"; | ||
import { Command } from "commander"; | ||
import { Action } from "../action.js"; | ||
|
||
const version: string = JSON.parse( | ||
await fs.readFile( | ||
path.resolve( | ||
path.dirname(fileURLToPath(import.meta.url)), | ||
"..", | ||
"..", | ||
"package.json", | ||
), | ||
"utf8", | ||
), | ||
).version; | ||
|
||
new Command() | ||
.name("tscx") | ||
.version(version) | ||
.description("The TypeScript Compiler. Run `tsc` under the hood.") | ||
.option( | ||
"-p, --project <path>", | ||
"Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'.", | ||
"tsconfig.json", | ||
) | ||
.option("-w, --watch", "Watch input files.") | ||
.option("--clean", "Remove output folder before before every compilation.") | ||
.option( | ||
"--copyfiles", | ||
"Copy non-ts files to output folder after every compilation.", | ||
) | ||
.option("--run <path>", "Run the specified js file after compilation success") | ||
.action((options) => { | ||
new Action(options).start(); | ||
}) | ||
.parse(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import fs from "node:fs"; | ||
import process from "node:process"; | ||
|
||
/** | ||
* @param filepath absolute filepath | ||
*/ | ||
async function clean(filepath: string) { | ||
await new Promise<void>((resolve, reject) => { | ||
fs.stat(filepath, (err) => { | ||
if (err) { | ||
return err.code === "ENOENT" ? resolve() : reject(err); // do nothing if file not found | ||
} | ||
fs.rm(filepath, { recursive: true }, (e) => (e ? reject(e) : resolve())); | ||
}); | ||
}); | ||
console.log(`Removed ${filepath}`); | ||
} | ||
|
||
const filepath = process.argv[2]; | ||
if (!filepath) { | ||
throw new Error("File path is required"); | ||
} | ||
|
||
await clean(filepath); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import fs from "node:fs/promises"; | ||
import path from "node:path"; | ||
import process from "node:process"; | ||
|
||
/** | ||
* Copy non-ts/non-js files to outDir | ||
* @param rootDir absolute path | ||
* @param outDir absolute path | ||
*/ | ||
async function copyfiles(rootDir: string, outDir: string) { | ||
rootDir = path.resolve(rootDir); | ||
outDir = path.resolve(outDir); | ||
async function walkDir(dir: string, cb: (filepath: string) => Promise<void>) { | ||
await Promise.all( | ||
(await fs.readdir(dir)) | ||
.map((filepath) => path.resolve(dir, filepath)) | ||
.map(async (filepath) => { | ||
if ((await fs.stat(filepath)).isDirectory()) { | ||
if ( | ||
filepath !== outDir && | ||
!filepath.endsWith(`${path.sep}node_modules`) | ||
) { | ||
await walkDir(filepath, cb); | ||
} | ||
} else { | ||
if (!/\.(js|cjs|mjs|jsx|ts|cts|mts|tsx)$/.test(filepath)) { | ||
await cb(filepath); | ||
} | ||
} | ||
}), | ||
); | ||
} | ||
await walkDir(rootDir, async (filepath) => { | ||
const dest = filepath.replace(rootDir, outDir); | ||
console.log("Copy", filepath, "=>", dest); | ||
await fs.copyFile(filepath, dest); | ||
}); | ||
} | ||
|
||
const rootDir = process.argv[2]; | ||
const outDir = process.argv[3]; | ||
if (!rootDir || !outDir) { | ||
throw new Error("`rootDir` and `outDir` are required"); | ||
} | ||
|
||
await copyfiles(rootDir, outDir); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { spawn } from "node:child_process"; | ||
import path from "node:path"; | ||
import process from "node:process"; | ||
import { fileURLToPath } from "node:url"; | ||
|
||
const __dirname = path.dirname(fileURLToPath(import.meta.url)); | ||
const CLEAN_PATH = path.resolve(__dirname, "clean.mjs"); | ||
const COPYFILES_PATH = path.resolve(__dirname, "copyfiles.mjs"); | ||
const TSC_PATH = path.resolve( | ||
process.cwd(), | ||
"node_modules", | ||
"typescript", | ||
"bin", | ||
"tsc", | ||
); | ||
|
||
export function clean(filepath: string) { | ||
console.log("Clean", filepath); | ||
return spawn("node", [CLEAN_PATH, filepath], { stdio: "inherit" }); | ||
} | ||
|
||
export function tsc(options: { project: string }) { | ||
console.log("Tsc", options); | ||
return spawn("node", [TSC_PATH, "--project", options.project], { | ||
stdio: "inherit", | ||
}); | ||
} | ||
|
||
export function copyfiles(rootDir: string, outDir: string) { | ||
console.log("Copyfiles", rootDir, "=>", outDir); | ||
return spawn("node", [COPYFILES_PATH, rootDir, outDir], { stdio: "inherit" }); | ||
} | ||
|
||
export function run(filepath: string) { | ||
console.log("Run", filepath); | ||
return spawn("node", [filepath], { stdio: "inherit" }); | ||
} |
Oops, something went wrong.