@atlaspack/reporter-dev-server 2.14.18-noselfbuild-3f2849b52.0 → 2.14.18-noselfbuild-342bd6c75.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,263 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _Server = require("./Server");
8
+ function _nullthrows() {
9
+ const data = _interopRequireDefault(require("nullthrows"));
10
+ _nullthrows = function () {
11
+ return data;
12
+ };
13
+ return data;
14
+ }
15
+ function _url() {
16
+ const data = _interopRequireDefault(require("url"));
17
+ _url = function () {
18
+ return data;
19
+ };
20
+ return data;
21
+ }
22
+ function _mimeTypes() {
23
+ const data = _interopRequireDefault(require("mime-types"));
24
+ _mimeTypes = function () {
25
+ return data;
26
+ };
27
+ return data;
28
+ }
29
+ function _ws() {
30
+ const data = _interopRequireDefault(require("ws"));
31
+ _ws = function () {
32
+ return data;
33
+ };
34
+ return data;
35
+ }
36
+ function _assert() {
37
+ const data = _interopRequireDefault(require("assert"));
38
+ _assert = function () {
39
+ return data;
40
+ };
41
+ return data;
42
+ }
43
+ function _utils() {
44
+ const data = require("@atlaspack/utils");
45
+ _utils = function () {
46
+ return data;
47
+ };
48
+ return data;
49
+ }
50
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
51
+ const FS_CONCURRENCY = 64;
52
+ const HMR_ENDPOINT = '/__parcel_hmr';
53
+ const BROADCAST_MAX_ASSETS = 10000;
54
+ class HMRServer {
55
+ unresolvedError = null;
56
+ bundleGraph = null;
57
+ constructor(options) {
58
+ this.options = options;
59
+ }
60
+ async start() {
61
+ let server = this.options.devServer;
62
+ if (!server) {
63
+ let result = await (0, _utils().createHTTPServer)({
64
+ https: this.options.https,
65
+ inputFS: this.options.inputFS,
66
+ outputFS: this.options.outputFS,
67
+ cacheDir: this.options.cacheDir,
68
+ listener: (req, res) => {
69
+ (0, _Server.setHeaders)(res);
70
+ if (!this.handle(req, res)) {
71
+ res.statusCode = 404;
72
+ res.end();
73
+ }
74
+ }
75
+ });
76
+ server = result.server;
77
+ server.listen(this.options.port, this.options.host);
78
+ this.stopServer = result.stop;
79
+ } else {
80
+ var _this$options$addMidd, _this$options;
81
+ (_this$options$addMidd = (_this$options = this.options).addMiddleware) === null || _this$options$addMidd === void 0 || _this$options$addMidd.call(_this$options, (req, res) => this.handle(req, res));
82
+ }
83
+ this.wss = new (_ws().default.Server)({
84
+ server
85
+ });
86
+ this.wss.on('connection', ws => {
87
+ if (this.unresolvedError) {
88
+ ws.send(JSON.stringify(this.unresolvedError));
89
+ }
90
+ });
91
+
92
+ // $FlowFixMe[incompatible-exact]
93
+ this.wss.on('error', err => this.handleSocketError(err));
94
+ }
95
+ handle(req, res) {
96
+ let {
97
+ pathname
98
+ } = _url().default.parse(req.originalUrl || req.url);
99
+ if (pathname != null && pathname.startsWith(HMR_ENDPOINT)) {
100
+ let id = pathname.slice(HMR_ENDPOINT.length + 1);
101
+ let bundleGraph = (0, _nullthrows().default)(this.bundleGraph);
102
+ let asset = bundleGraph.getAssetById(id);
103
+ this.getHotAssetContents(asset).then(output => {
104
+ res.setHeader('Content-Type', _mimeTypes().default.contentType(asset.type));
105
+ res.end(output);
106
+ });
107
+ return true;
108
+ }
109
+ return false;
110
+ }
111
+ async stop() {
112
+ if (this.stopServer != null) {
113
+ await this.stopServer();
114
+ this.stopServer = null;
115
+ }
116
+ this.wss.close();
117
+ }
118
+ async emitError(options, diagnostics) {
119
+ let renderedDiagnostics = await Promise.all(diagnostics.map(d => (0, _utils().prettyDiagnostic)(d, options)));
120
+
121
+ // store the most recent error so we can notify new connections
122
+ // and so we can broadcast when the error is resolved
123
+ this.unresolvedError = {
124
+ type: 'error',
125
+ diagnostics: {
126
+ ansi: renderedDiagnostics,
127
+ html: renderedDiagnostics.map((d, i) => {
128
+ return {
129
+ message: (0, _utils().ansiHtml)(d.message),
130
+ stack: (0, _utils().ansiHtml)(d.stack),
131
+ frames: d.frames.map(f => ({
132
+ location: f.location,
133
+ code: (0, _utils().ansiHtml)(f.code)
134
+ })),
135
+ hints: d.hints.map(hint => (0, _utils().ansiHtml)(hint)),
136
+ documentation: diagnostics[i].documentationURL ?? ''
137
+ };
138
+ })
139
+ }
140
+ };
141
+ this.broadcast(this.unresolvedError);
142
+ }
143
+ async emitUpdate(event) {
144
+ this.unresolvedError = null;
145
+ this.bundleGraph = event.bundleGraph;
146
+ let changedAssets = new Set(event.changedAssets.values());
147
+ if (changedAssets.size === 0) return;
148
+ let queue = new (_utils().PromiseQueue)({
149
+ maxConcurrent: FS_CONCURRENCY
150
+ });
151
+ for (let asset of changedAssets) {
152
+ if (asset.type !== 'js' && asset.type !== 'css') {
153
+ // If all of the incoming dependencies of the asset actually resolve to a JS asset
154
+ // rather than the original, we can mark the runtimes as changed instead. URL runtimes
155
+ // have a cache busting query param added with HMR enabled which will trigger a reload.
156
+ let runtimes = new Set();
157
+ let incomingDeps = event.bundleGraph.getIncomingDependencies(asset);
158
+ let isOnlyReferencedByRuntimes = incomingDeps.every(dep => {
159
+ let resolved = event.bundleGraph.getResolvedAsset(dep);
160
+ let isRuntime = (resolved === null || resolved === void 0 ? void 0 : resolved.type) === 'js' && resolved !== asset;
161
+ if (resolved && isRuntime) {
162
+ runtimes.add(resolved);
163
+ }
164
+ return isRuntime;
165
+ });
166
+ if (isOnlyReferencedByRuntimes) {
167
+ for (let runtime of runtimes) {
168
+ changedAssets.add(runtime);
169
+ }
170
+ continue;
171
+ }
172
+ }
173
+ queue.add(async () => {
174
+ let dependencies = event.bundleGraph.getDependencies(asset);
175
+ let depsByBundle = {};
176
+ for (let bundle of event.bundleGraph.getBundlesWithAsset(asset)) {
177
+ let deps = {};
178
+ for (let dep of dependencies) {
179
+ let resolved = event.bundleGraph.getResolvedAsset(dep, bundle);
180
+ if (resolved) {
181
+ deps[getSpecifier(dep)] = event.bundleGraph.getAssetPublicId(resolved);
182
+ }
183
+ }
184
+ depsByBundle[bundle.id] = deps;
185
+ }
186
+ return {
187
+ id: event.bundleGraph.getAssetPublicId(asset),
188
+ url: this.getSourceURL(asset),
189
+ type: asset.type,
190
+ // No need to send the contents of non-JS assets to the client.
191
+ output: asset.type === 'js' ? await this.getHotAssetContents(asset) : '',
192
+ envHash: asset.env.id,
193
+ outputFormat: asset.env.outputFormat,
194
+ depsByBundle
195
+ };
196
+ });
197
+ }
198
+ let assets = await queue.run();
199
+ if (assets.length >= BROADCAST_MAX_ASSETS) {
200
+ // Too many assets to send via an update without errors, just reload instead
201
+ this.broadcast({
202
+ type: 'reload'
203
+ });
204
+ } else {
205
+ this.broadcast({
206
+ type: 'update',
207
+ assets
208
+ });
209
+ }
210
+ }
211
+ async getHotAssetContents(asset) {
212
+ let output = await asset.getCode();
213
+ let bundleGraph = (0, _nullthrows().default)(this.bundleGraph);
214
+ if (asset.type === 'js') {
215
+ let publicId = bundleGraph.getAssetPublicId(asset);
216
+ output = `parcelHotUpdate['${publicId}'] = function (require, module, exports) {${output}}`;
217
+ }
218
+ let sourcemap = await asset.getMap();
219
+ if (sourcemap) {
220
+ let sourcemapStringified = await sourcemap.stringify({
221
+ format: 'inline',
222
+ sourceRoot: _Server.SOURCES_ENDPOINT + '/',
223
+ // $FlowFixMe
224
+ fs: asset.fs
225
+ });
226
+ (0, _assert().default)(typeof sourcemapStringified === 'string');
227
+ output += `\n//# sourceMappingURL=${sourcemapStringified}`;
228
+ output += `\n//# sourceURL=${encodeURI(this.getSourceURL(asset))}\n`;
229
+ }
230
+ return output;
231
+ }
232
+ getSourceURL(asset) {
233
+ let origin = '';
234
+ if (!this.options.devServer) {
235
+ origin = `http://${this.options.host || 'localhost'}:${this.options.port}`;
236
+ }
237
+ return origin + HMR_ENDPOINT + '/' + asset.id;
238
+ }
239
+ handleSocketError(err) {
240
+ if (err.code === 'ECONNRESET') {
241
+ // This gets triggered on page refresh, ignore this
242
+ return;
243
+ }
244
+ this.options.logger.warn({
245
+ origin: '@atlaspack/reporter-dev-server',
246
+ message: `[${err.code}]: ${err.message}`,
247
+ stack: err.stack
248
+ });
249
+ }
250
+ broadcast(msg) {
251
+ const json = JSON.stringify(msg);
252
+ for (let ws of this.wss.clients) {
253
+ ws.send(json);
254
+ }
255
+ }
256
+ }
257
+ exports.default = HMRServer;
258
+ function getSpecifier(dep) {
259
+ if (typeof dep.meta.placeholder === 'string') {
260
+ return dep.meta.placeholder;
261
+ }
262
+ return dep.specifier;
263
+ }