1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const tslib_1 = require("tslib");
|
4 | const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
5 | const child_process_1 = require("child_process");
|
6 | const pstree_remy_1 = tslib_1.__importStar(require("pstree.remy"));
|
7 | const platform_1 = require("../util/platform");
|
8 | function invariant(condition, message) {
|
9 | if (!condition) {
|
10 | const err = new Error(message);
|
11 | err.name = 'Invariant Violation';
|
12 | throw err;
|
13 | }
|
14 | }
|
15 | class AppController {
|
16 | constructor(executablePath, argv) {
|
17 | this.state = {
|
18 | appRunning: false,
|
19 | proc: null,
|
20 | pid: null,
|
21 | };
|
22 | this.executablePath = executablePath;
|
23 | this.argv = argv;
|
24 | }
|
25 | stopApp() {
|
26 | return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
27 | return new Promise(resolve => {
|
28 | if (this.state.appRunning) {
|
29 | console.log('Sending SIGTERM signal to app...');
|
30 | const { pid } = this.state;
|
31 | const closeHandler = (code, signal) => {
|
32 | this.setState({
|
33 | appRunning: false,
|
34 | proc: null,
|
35 | pid: null,
|
36 | });
|
37 | resolve();
|
38 | };
|
39 | if (platform_1.isWindows()) {
|
40 | child_process_1.exec('taskkill /pid ' + pid + ' /T /F').on('close', closeHandler);
|
41 | }
|
42 | else {
|
43 |
|
44 | pstree_remy_1.default(pid, (_, children) => {
|
45 | if (pstree_remy_1.hasPS) {
|
46 |
|
47 | child_process_1.spawn('kill', ['-s', 'SIGTERM', pid].concat(children)).on('close', closeHandler);
|
48 | }
|
49 | else {
|
50 | const pids = children.concat(pid).sort();
|
51 | pids.forEach(childPid => {
|
52 |
|
53 | child_process_1.exec('kill -15 ' + childPid).on('close', closeHandler);
|
54 | });
|
55 | }
|
56 | });
|
57 | }
|
58 | }
|
59 | else {
|
60 | resolve();
|
61 | }
|
62 | });
|
63 | });
|
64 | }
|
65 | runApp() {
|
66 | invariant(!this.state.appRunning, "Can't start app when app is already running!");
|
67 |
|
68 | const proc = child_process_1.spawn('node', [this.executablePath, ...this.argv]);
|
69 |
|
70 | proc.on('error', e => {
|
71 | console.log(chalk_1.default.red('Failed to start app: ' + e.message));
|
72 | this.setState({
|
73 | appRunning: false,
|
74 | proc: null,
|
75 | pid: null,
|
76 | });
|
77 | });
|
78 | proc.on('exit', (code, signal) => {
|
79 | if (code !== null) {
|
80 | console.log(code > 0
|
81 | ? chalk_1.default.red('App exited with code ' + code + '.')
|
82 | : chalk_1.default.green('App exited with code ' + code + '.'));
|
83 | }
|
84 | if (signal !== null) {
|
85 | console.log(signal !== 'SIGTERM'
|
86 | ? chalk_1.default.red('App killed with signal ' + signal + '.')
|
87 | : chalk_1.default.green('App killed with signal SIGTERM.'));
|
88 | }
|
89 | this.setState({
|
90 | appRunning: false,
|
91 | proc: null,
|
92 | pid: null,
|
93 | });
|
94 | });
|
95 |
|
96 | proc.stdout.pipe(process.stdout);
|
97 | proc.stderr.pipe(process.stderr);
|
98 | console.log(chalk_1.default.green('App started!'));
|
99 | this.setState({
|
100 | proc,
|
101 | pid: proc.pid.toString(),
|
102 | appRunning: true,
|
103 | });
|
104 | }
|
105 | setState(state) {
|
106 | this.state = state;
|
107 | }
|
108 | }
|
109 | exports.AppController = AppController;
|
110 |
|
\ | No newline at end of file |