UNPKG

5.03 kBJavaScriptView Raw
1"use strict";
2
3var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
5var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
6
7var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
8
9const http = require('http');
10
11const https = require('https');
12
13const WebSocket = require('ws');
14
15const generateCertificate = require('./utils/generateCertificate');
16
17const getCertificate = require('./utils/getCertificate');
18
19const logger = require('@parcel/logger');
20
21class HMRServer {
22 start(options = {}) {
23 var _this = this;
24
25 return (0, _asyncToGenerator2.default)(function* () {
26 yield new Promise(
27 /*#__PURE__*/
28 function () {
29 var _ref = (0, _asyncToGenerator2.default)(function* (resolve) {
30 if (!options.https) {
31 _this.server = http.createServer();
32 } else if (typeof options.https === 'boolean') {
33 _this.server = https.createServer(generateCertificate(options));
34 } else {
35 _this.server = https.createServer((yield getCertificate(options.https)));
36 }
37
38 let websocketOptions = {
39 server: _this.server
40 };
41
42 if (options.hmrHostname) {
43 websocketOptions.origin = `${options.https ? 'https' : 'http'}://${options.hmrHostname}`;
44 }
45
46 _this.wss = new WebSocket.Server(websocketOptions);
47
48 _this.server.listen(options.hmrPort, resolve);
49 });
50
51 return function (_x) {
52 return _ref.apply(this, arguments);
53 };
54 }());
55
56 _this.wss.on('connection', ws => {
57 ws.onerror = _this.handleSocketError;
58
59 if (_this.unresolvedError) {
60 ws.send(JSON.stringify(_this.unresolvedError));
61 }
62 });
63
64 _this.wss.on('error', _this.handleSocketError);
65
66 return _this.wss._server.address().port;
67 })();
68 }
69
70 stop() {
71 this.wss.close();
72 this.server.close();
73 }
74
75 emitError(err) {
76 let _logger$formatError = logger.formatError(err),
77 message = _logger$formatError.message,
78 stack = _logger$formatError.stack; // store the most recent error so we can notify new connections
79 // and so we can broadcast when the error is resolved
80
81
82 this.unresolvedError = {
83 type: 'error',
84 error: {
85 message,
86 stack
87 }
88 };
89 this.broadcast(this.unresolvedError);
90 }
91
92 emitUpdate(assets, reload = false) {
93 if (this.unresolvedError) {
94 this.unresolvedError = null;
95 this.broadcast({
96 type: 'error-resolved'
97 });
98 }
99
100 const shouldReload = reload || assets.some(asset => asset.hmrPageReload);
101
102 if (shouldReload) {
103 this.broadcast({
104 type: 'reload'
105 });
106 } else {
107 this.broadcast({
108 type: 'update',
109 assets: assets.map(asset => {
110 let deps = {};
111 var _iteratorNormalCompletion = true;
112 var _didIteratorError = false;
113 var _iteratorError = undefined;
114
115 try {
116 for (var _iterator = asset.depAssets[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
117 let _step$value = (0, _slicedToArray2.default)(_step.value, 2),
118 dep = _step$value[0],
119 depAsset = _step$value[1];
120
121 deps[dep.name] = depAsset.id;
122 }
123 } catch (err) {
124 _didIteratorError = true;
125 _iteratorError = err;
126 } finally {
127 try {
128 if (!_iteratorNormalCompletion && _iterator.return != null) {
129 _iterator.return();
130 }
131 } finally {
132 if (_didIteratorError) {
133 throw _iteratorError;
134 }
135 }
136 }
137
138 return {
139 id: asset.id,
140 type: asset.type,
141 generated: asset.generated,
142 deps: deps
143 };
144 })
145 });
146 }
147 }
148
149 handleSocketError(err) {
150 if (err.error.code === 'ECONNRESET') {
151 // This gets triggered on page refresh, ignore this
152 return;
153 }
154
155 logger.warn(err);
156 }
157
158 broadcast(msg) {
159 const json = JSON.stringify(msg);
160 var _iteratorNormalCompletion2 = true;
161 var _didIteratorError2 = false;
162 var _iteratorError2 = undefined;
163
164 try {
165 for (var _iterator2 = this.wss.clients[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
166 let ws = _step2.value;
167 ws.send(json);
168 }
169 } catch (err) {
170 _didIteratorError2 = true;
171 _iteratorError2 = err;
172 } finally {
173 try {
174 if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
175 _iterator2.return();
176 }
177 } finally {
178 if (_didIteratorError2) {
179 throw _iteratorError2;
180 }
181 }
182 }
183 }
184
185}
186
187module.exports = HMRServer;
\No newline at end of file