Added better windows support for out of the box usage

canary
WolverinDEV 2019-12-03 16:46:40 +01:00
parent fe3751712b
commit 86074335dc
1 changed files with 74 additions and 58 deletions

132
file.ts
View File

@ -724,43 +724,87 @@ namespace server {
} }
namespace watcher { namespace watcher {
export class TSCWatcher { function execute(cmd: string, args: string[]) : ChildProcess {
if(os.platform() === "win32")
return cp.spawn(process.env.comspec, ["/C", cmd, ...args], {
stdio: "pipe",
cwd: __dirname,
env: process.env
});
else
this._process = cp.spawn(cmd, args, {
cwd: __dirname,
stdio: "pipe",
detached: true
});
}
export abstract class Watcher {
readonly name: string;
private _process: ChildProcess; private _process: ChildProcess;
constructor() { } private _callback_init: () => any;
private _callback_init_fail: (msg: string) => any;
protected constructor(name: string) {
this.name = name;
}
async start() { async start() {
if(this._process) throw "watcher already started"; if(this._process) throw "watcher already started";
this._process = cp.spawn("npm", ["run", "ttsc", "--", "-w"], { const command = this.start_command();
cwd: __dirname, this._process = execute(command[0], command.slice(1));
stdio: "pipe",
});
this._process.unref(); this._process.unref();
this._process.stdout.on("readable", this.handle_stdout_readable.bind(this)); this._process.stdout.on("readable", this.handle_stdout_readable.bind(this));
this._process.stderr.on("readable", this.handle_stderr_readable.bind(this)); this._process.stderr.on("readable", this.handle_stderr_readable.bind(this));
this._process.addListener("exit", this.handle_exit.bind(this)); this._process.addListener("exit", this.handle_exit.bind(this));
this._process.addListener("error", this.handle_error.bind(this)); this._process.addListener("error", this.handle_error.bind(this));
console.log("TSC Watcher started."); try {
await new Promise((resolve, reject) => {
const id = setTimeout(reject, 5000, "timeout");
this._callback_init = () => {
clearTimeout(id);
resolve();
};
this._callback_init_fail = err => {
clearTimeout(id);
reject(err);
};
});
} catch(e) {
try { this.stop(); } catch (_) { }
throw e;
} finally {
this._callback_init_fail = undefined;
this._callback_init = undefined;
}
console.log("%s started.", this.name);
} }
protected abstract start_command() : string[];
async stop() { async stop() {
if(!this._process) return; if(!this._process) return;
console.log("TSC Watcher stopped."); console.log("%s stopped.", this.name);
this._process.kill("SIGTERM") this._process.kill("SIGTERM");
this._process = undefined; this._process = undefined;
} }
private handle_exit(code: number | null, signal: string | null) { private handle_exit(code: number | null, signal: string | null) {
console.log("TSC Watcher exited with code %d (%s)", code, signal); console.log("%s exited with code %d (%s)", this.name, code, signal);
if(this._callback_init_fail)
this._callback_init_fail("unexpected exit with code " + code);
} }
private handle_stdout_readable() { private handle_stdout_readable() {
const buffer: Buffer = this._process.stdout.read(this._process.stdout.readableLength); const buffer: Buffer = this._process.stdout.read(this._process.stdout.readableLength);
if(!buffer) return; if(!buffer) return;
if(this._callback_init)
this._callback_init();
//console.log("TSCWatcher read %d bytes", buffer.length); //console.log("TSCWatcher read %d bytes", buffer.length);
} }
@ -768,65 +812,37 @@ namespace watcher {
const buffer: Buffer = this._process.stdout.read(this._process.stdout.readableLength); const buffer: Buffer = this._process.stdout.read(this._process.stdout.readableLength);
if(!buffer) return; if(!buffer) return;
console.log("TSC Watcher read %d error bytes:", buffer.length); console.log("%s read %d error bytes:", this.name, buffer.length);
console.log(buffer.toString()); console.log(buffer.toString());
} }
private handle_error(err: Error) { private handle_error(err: Error) {
console.log("TSC Watcher received error: %o", err); if(this._callback_init_fail) {
console.debug("%s received startup error: %o", this.name, err);
this._callback_init_fail("received error: " + err.message);
} else {
console.log("%s received error: %o", this.name, err);
}
} }
} }
export class TSCWatcher extends Watcher {
export class SASSWatcher { constructor() {
private _process: ChildProcess; super("TSC Watcher");
constructor() { }
async start() {
if(this._process) throw "watcher already started";
this._process = cp.spawn("npm", ["run", "sass", "--", "--watch"], {
cwd: __dirname,
stdio: "pipe",
});
this._process.unref();
this._process.stdout.on("readable", this.handle_stdout_readable.bind(this));
this._process.stderr.on("readable", this.handle_stderr_readable.bind(this));
this._process.addListener("exit", this.handle_exit.bind(this));
this._process.addListener("error", this.handle_error.bind(this));
console.log("SASS Watcher started.");
} }
async stop() { protected start_command(): string[] {
if(!this._process) return; return ["npm", "run", "ttsc", "--", "-w"];
}
}
console.log("SASS Watcher stopped."); export class SASSWatcher extends Watcher {
this._process.kill("SIGTERM") constructor() {
super("SASS Watcher");
} }
private handle_exit(code: number | null, signal: string | null) { protected start_command(): string[] {
console.log("SASS Watcher exited with code %d (%s)", code, signal); return ["npm", "run", "sass", "--", "--watch"];
}
private handle_stdout_readable() {
const buffer: Buffer = this._process.stdout.read(this._process.stdout.readableLength);
if(!buffer) return;
//console.log("TSCWatcher read %d bytes", buffer.length);
}
private handle_stderr_readable() {
const buffer: Buffer = this._process.stdout.read(this._process.stdout.readableLength);
if(!buffer) return;
console.log("SASS Watcher read %d error bytes:", buffer.length);
console.log(buffer.toString());
}
private handle_error(err: Error) {
console.log("SASS Watcher received error: %o", err);
} }
} }
} }