forked from angular/angular
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtsc_watch.ts
More file actions
142 lines (129 loc) · 4.42 KB
/
tsc_watch.ts
File metadata and controls
142 lines (129 loc) · 4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import {spawn} from 'child_process';
import {resolve} from 'url';
enum State {
idle, waiting, error
}
export const TSC = 'node_modules/typescript/bin/tsc';
export type Command = (stdIn, stdErr) => Promise<number>;
export class TscWatch {
private tsconfig:string;
private start:string|RegExp;
private error:string|RegExp;
private complete:string|RegExp;
private onStartCmds:Array<string[]|Command>;
private onChangeCmds:Array<string[]|Command>;
private state:State;
private triggered:Promise<number> = null;
private runOnce: boolean = false;
constructor({tsconfig, start, error, complete, onStartCmds=null, onChangeCmds=null}:
{tsconfig:string, error:string|RegExp, start:string, complete:string,
onStartCmds?:Array<string[]|Command>, onChangeCmds?:Array<string[]|Command>})
{
console.log('Watching:', tsconfig, 'in', process.cwd());
this.tsconfig = tsconfig;
this.start = start;
this.error = error;
this.complete = complete;
this.onStartCmds = onStartCmds || [];
this.onChangeCmds = onChangeCmds || [];
}
watch() {
var args = [TSC, '--project', this.tsconfig];
if (!this.runOnce) args.push('--watch');
this.runCmd(args, {}, (d) => this.consumeLine(d, false), (d) => this.consumeLine(d, true));
this.state = State.waiting;
this.onStartCmds.forEach((cmd) => this.runCmd(cmd, () => null, () => null));
}
private runCmd(argsOrCmd: string[]|Command, env?,
stdOut = pipeStdOut, stdErr = pipeStdErr):Promise<number>
{
if (typeof argsOrCmd == 'function') {
return (argsOrCmd as Command)(stdErr, stdOut);
} else if (argsOrCmd instanceof Array) {
var args = argsOrCmd as Array<string>;
return <any>new Promise((resolve, reject) => {
var [cmd, ...options] = args;
console.log('=====>', cmd, options.join(' '));
var childProcess = spawn(cmd, options, {stdio: 'pipe'});
childProcess.stdout.on('data', stdOut);
childProcess.stderr.on('data', stdErr);
var onExit = () => childProcess.kill();
childProcess.on('close', (code: number) => {
process.removeListener('exit', onExit);
console.log('EXIT:', code, '<=====', args.join(' '));
code ? reject(code) : resolve(code);
});
process.on('exit', onExit);
}).catch(reportError);
} else {
throw new Error('Expecting function or an array of strings...');
}
}
run() {
this.runOnce = true;
this.watch();
}
consumeLine(buffer:Buffer, isStdError:boolean) {
var line = '' + buffer;
if (contains(line, this.start)) {
console.log('==============================================================================');
stdOut(buffer, isStdError);
this.state = State.waiting;
} else if (contains(line, this.error)) {
stdOut(buffer, isStdError);
this.state = State.error;
} else if (contains(line, this.complete)) {
stdOut(buffer, isStdError);
console.log('------------------------------------------------------------------------------');
if (this.state == State.error) {
console.log('Errors found.... (response not triggered)');
if (this.runOnce) process.exit(1);
this.state = State.idle;
} else {
if (this.triggered) {
this.triggered.then(() => this.triggerCmds());
} else {
this.triggerCmds();
}
}
} else {
stdOut(buffer, isStdError);
}
}
triggerCmds() {
var cmdPromise:Promise<number> = Promise.resolve();
this.onChangeCmds.forEach((cmd:string[]|Command) => {
cmdPromise = cmdPromise.then(() => {
return this.runCmd(<string[]>cmd);
})
});
cmdPromise.then(() => this.triggered = null, reportError);
this.triggered = cmdPromise;
}
}
function stdOut(data:Buffer, isStdError:boolean) {
if (isStdError) {
process.stderr.write(data);
} else {
process.stdout.write(data);
}
}
function contains(line: string, text: string| RegExp): boolean {
if (typeof text == 'string') {
return line.indexOf(text as string) != -1;
} else if (text instanceof RegExp) {
return (text as RegExp).test(line);
} else {
throw new Error('Unknown: ' + text);
}
}
function reportError(e) {
if (e.message && e.stack) {
console.error(e.message);
console.error(e.stack);
} else {
console.error(e);
}
}
function pipeStdOut(d) { process.stdout.write(d); }
function pipeStdErr(d) { process.stderr.write(d); }