1 | "use strict";
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | const http_1 = __importDefault(require("http"));
|
6 | const https_1 = __importDefault(require("https"));
|
7 | const fs_1 = __importDefault(require("fs"));
|
8 | const path_1 = __importDefault(require("path"));
|
9 | const messages_1 = __importDefault(require("./messages"));
|
10 | const middleware_1 = __importDefault(require("./middleware"));
|
11 | const events_1 = __importDefault(require("events"));
|
12 | class Server extends events_1.default {
|
13 | constructor(watcher, host, port, connect = require('connect'), ui, ssl, sslKey, sslCert) {
|
14 | super();
|
15 | this._watcher = watcher;
|
16 | this._builder = watcher.builder;
|
17 | this._host = host;
|
18 | this._port = parseInt(port, 10);
|
19 | this._ssl = ssl;
|
20 | this._sslKey = sslKey;
|
21 | this._sslCert = sslCert;
|
22 | this._connect = connect;
|
23 | this._url = `http${this._ssl ? 's' : ''}://${this._host}:${this._port}`;
|
24 | this.app = this.instance = null;
|
25 | this._boundStop = this.stop.bind(this);
|
26 | this._started = false;
|
27 | this.ui = ui;
|
28 | if (watcher.constructor.name !== 'Watcher') {
|
29 | throw new Error('Expected Watcher instance');
|
30 | }
|
31 | if (typeof host !== 'string') {
|
32 | throw new Error('Expected host to bind to (e.g. "localhost")');
|
33 | }
|
34 | if (typeof port !== 'number' || port !== port) {
|
35 | throw new Error('Expected port to bind to (e.g. 4200)');
|
36 | }
|
37 | }
|
38 | async start() {
|
39 | if (this._started) {
|
40 | throw new Error('Watcher.prototype.start() must not be called more than once');
|
41 | }
|
42 | const promise = new Promise((resolve, reject) => {
|
43 | this.app = this._connect().use(middleware_1.default(this._watcher));
|
44 | if (this._ssl) {
|
45 | let sslOptions;
|
46 | try {
|
47 | sslOptions = {
|
48 | key: fs_1.default.readFileSync(this._sslKey),
|
49 | cert: fs_1.default.readFileSync(this._sslCert),
|
50 | };
|
51 | }
|
52 | catch (err) {
|
53 | throw new Error(`SSL key and certificate files should be present at ${path_1.default.join(process.cwd(), this._sslKey)} and ${path_1.default.join(process.cwd(), this._sslCert)} respectively.`);
|
54 | }
|
55 | this.instance = https_1.default.createServer(sslOptions, this.app);
|
56 | }
|
57 | else {
|
58 | this.instance = http_1.default.createServer(this.app);
|
59 | }
|
60 | this.instance.listen(this._port, this._host);
|
61 | this.instance.on('listening', () => {
|
62 | this.ui.writeLine(`Serving on ${this._url}\n`);
|
63 | resolve(this._watcher.start());
|
64 | });
|
65 | this.instance.on('error', (error) => {
|
66 | if (error.code !== 'EADDRINUSE') {
|
67 | throw error;
|
68 | }
|
69 | let message = `Oh snap 😫. It appears a server is already running on ${this._url}\n`;
|
70 | message += `Are you perhaps already running serve in another terminal window?\n`;
|
71 | reject(new Error(message));
|
72 | });
|
73 | process.addListener('SIGINT', this._boundStop);
|
74 | process.addListener('SIGTERM', this._boundStop);
|
75 | this._watcher.on('buildSuccess', () => {
|
76 | this.emit('buildSuccess');
|
77 | messages_1.default.onBuildSuccess(this._builder, this.ui);
|
78 | });
|
79 | this._watcher.on('buildFailure', (err) => {
|
80 | this.emit('buildFailure');
|
81 | this.ui.writeLine('build failure', 'ERROR');
|
82 | this.ui.writeError(err);
|
83 | });
|
84 | });
|
85 | try {
|
86 | await promise;
|
87 | }
|
88 | finally {
|
89 | await this.stop();
|
90 | }
|
91 | }
|
92 | _detachListeners() {
|
93 | process.removeListener('SIGINT', this._boundStop);
|
94 | process.removeListener('SIGTERM', this._boundStop);
|
95 | }
|
96 | async stop() {
|
97 | this._detachListeners();
|
98 | if (this.instance) {
|
99 | this.instance.close();
|
100 | }
|
101 | await this._watcher.quit();
|
102 | await this._builder.cleanup();
|
103 | }
|
104 | }
|
105 | function serve(watcher, host, port, _connect = require('connect'), _process = process, ui, ssl, sslKey, sslCert) {
|
106 | const server = new Server(watcher, host, port, _connect, ui, ssl, sslKey, sslCert);
|
107 | return server
|
108 | .start()
|
109 | .then(() => _process.exit(0))
|
110 | .catch(err => {
|
111 | ui.writeLine('Broccoli Cleanup error:', 'ERROR');
|
112 | ui.writeError(err);
|
113 | _process.exit(1);
|
114 | });
|
115 | }
|
116 | ;
|
117 | module.exports = {
|
118 | Server,
|
119 | serve
|
120 | };
|
121 |
|
\ | No newline at end of file |