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