Asher 6d6c5e18d1
Fix watch script ignoring stdout
This was lost due to the change from fork to spawn.
2023-02-08 11:42:28 -09:00

142 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { spawn, ChildProcess } from "child_process"
import * as path from "path"
import { onLine, OnLineCallback } from "../../src/node/util"
interface DevelopmentCompilers {
[key: string]: ChildProcess | undefined
vscode: ChildProcess
vscodeWebExtensions: ChildProcess
codeServer: ChildProcess
plugins: ChildProcess | undefined
}
class Watcher {
private rootPath = path.resolve(process.cwd())
private readonly paths = {
/** Path to uncompiled VS Code source. */
vscodeDir: path.join(this.rootPath, "lib/vscode"),
pluginDir: process.env.PLUGIN_DIR,
}
//#region Web Server
/** Development web server. */
private webServer: ChildProcess | undefined
private reloadWebServer = (): void => {
if (this.webServer) {
this.webServer.kill()
}
// Pass CLI args, save for `node` and the initial script name.
const args = process.argv.slice(2)
this.webServer = spawn("node", [path.join(this.rootPath, "out/node/entry.js"), ...args])
onLine(this.webServer, (line) => console.log("[code-server]", line))
const { pid } = this.webServer
this.webServer.on("exit", () => console.log("[code-server]", `Web process ${pid} exited`))
console.log("\n[code-server]", `Spawned web server process ${pid}`)
}
//#endregion
//#region Compilers
private readonly compilers: DevelopmentCompilers = {
codeServer: spawn("tsc", ["--watch", "--pretty", "--preserveWatchOutput"], { cwd: this.rootPath }),
vscode: spawn("yarn", ["watch"], { cwd: this.paths.vscodeDir }),
vscodeWebExtensions: spawn("yarn", ["watch-web"], { cwd: this.paths.vscodeDir }),
plugins: this.paths.pluginDir ? spawn("yarn", ["build", "--watch"], { cwd: this.paths.pluginDir }) : undefined,
}
public async initialize(): Promise<void> {
for (const event of ["SIGINT", "SIGTERM"]) {
process.on(event, () => this.dispose(0))
}
for (const [processName, devProcess] of Object.entries(this.compilers)) {
if (!devProcess) continue
devProcess.on("exit", (code) => {
console.log(`[${processName}]`, "Terminated unexpectedly")
this.dispose(code)
})
if (devProcess.stderr) {
devProcess.stderr.on("data", (d: string | Uint8Array) => process.stderr.write(d))
}
}
onLine(this.compilers.vscode, this.parseVSCodeLine)
onLine(this.compilers.codeServer, this.parseCodeServerLine)
if (this.compilers.plugins) {
onLine(this.compilers.plugins, this.parsePluginLine)
}
}
//#endregion
//#region Line Parsers
private parseVSCodeLine: OnLineCallback = (strippedLine, originalLine) => {
if (!strippedLine.length) return
console.log("[Code OSS]", originalLine)
if (strippedLine.includes("Finished compilation with")) {
console.log("[Code OSS] Finished compiling! ", "(Refresh your web browser )")
this.reloadWebServer()
}
}
private parseCodeServerLine: OnLineCallback = (strippedLine, originalLine) => {
if (!strippedLine.length) return
console.log("[Compiler][code-server]", originalLine)
if (strippedLine.includes("Watching for file changes")) {
console.log("[Compiler][code-server]", "Finished compiling!", "(Refresh your web browser )")
this.reloadWebServer()
}
}
private parsePluginLine: OnLineCallback = (strippedLine, originalLine) => {
if (!strippedLine.length) return
console.log("[Compiler][Plugin]", originalLine)
if (strippedLine.includes("Watching for file changes...")) {
this.reloadWebServer()
}
}
//#endregion
//#region Utilities
private dispose(code: number | null): void {
for (const [processName, devProcess] of Object.entries(this.compilers)) {
console.log(`[${processName}]`, "Killing...\n")
devProcess?.removeAllListeners()
devProcess?.kill()
}
process.exit(typeof code === "number" ? code : 0)
}
//#endregion
}
async function main(): Promise<void> {
try {
const watcher = new Watcher()
await watcher.initialize()
} catch (error: any) {
console.error(error.message)
process.exit(1)
}
}
main()