@rushstack/heft-webpack5-plugin 0.6.6 → 0.7.0-rc.5

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,410 @@
1
+ "use strict";
2
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
+ // See LICENSE in the project root for license information.
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
17
+ }) : function(o, v) {
18
+ o["default"] = v;
19
+ });
20
+ var __importStar = (this && this.__importStar) || function (mod) {
21
+ if (mod && mod.__esModule) return mod;
22
+ var result = {};
23
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
24
+ __setModuleDefault(result, mod);
25
+ return result;
26
+ };
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.PLUGIN_NAME = void 0;
29
+ const tapable_1 = require("tapable");
30
+ const debug_certificate_manager_1 = require("@rushstack/debug-certificate-manager");
31
+ const node_core_library_1 = require("@rushstack/node-core-library");
32
+ const WebpackConfigurationLoader_1 = require("./WebpackConfigurationLoader");
33
+ const DeferredWatchFileSystem_1 = require("./DeferredWatchFileSystem");
34
+ /**
35
+ * @public
36
+ */
37
+ exports.PLUGIN_NAME = 'webpack5-plugin';
38
+ const SERVE_PARAMETER_LONG_NAME = '--serve';
39
+ const WEBPACK_PACKAGE_NAME = 'webpack';
40
+ const WEBPACK_DEV_SERVER_PACKAGE_NAME = 'webpack-dev-server';
41
+ const WEBPACK_DEV_SERVER_ENV_VAR_NAME = 'WEBPACK_DEV_SERVER';
42
+ const WEBPACK_DEV_MIDDLEWARE_PACKAGE_NAME = 'webpack-dev-middleware';
43
+ const UNINITIALIZED = 'UNINITIALIZED';
44
+ /**
45
+ * @internal
46
+ */
47
+ class Webpack5Plugin {
48
+ constructor() {
49
+ this._isServeMode = false;
50
+ this._webpackConfiguration = UNINITIALIZED;
51
+ this._warnings = [];
52
+ this._errors = [];
53
+ }
54
+ get accessor() {
55
+ if (!this._accessor) {
56
+ this._accessor = {
57
+ hooks: {
58
+ onLoadConfiguration: new tapable_1.AsyncSeriesBailHook(),
59
+ onConfigure: new tapable_1.AsyncSeriesHook(['webpackConfiguration']),
60
+ onAfterConfigure: new tapable_1.AsyncParallelHook(['webpackConfiguration']),
61
+ onEmitStats: new tapable_1.AsyncParallelHook(['webpackStats'])
62
+ },
63
+ parameters: {
64
+ isServeMode: this._isServeMode
65
+ }
66
+ };
67
+ }
68
+ return this._accessor;
69
+ }
70
+ apply(taskSession, heftConfiguration, options) {
71
+ this._isServeMode = taskSession.parameters.getFlagParameter(SERVE_PARAMETER_LONG_NAME).value;
72
+ if (!taskSession.parameters.watch && this._isServeMode) {
73
+ throw new Error(`The ${JSON.stringify(SERVE_PARAMETER_LONG_NAME)} parameter is only available when running in watch mode.`);
74
+ }
75
+ taskSession.hooks.run.tapPromise(exports.PLUGIN_NAME, async (runOptions) => {
76
+ await this._runWebpackAsync(taskSession, heftConfiguration, options);
77
+ });
78
+ taskSession.hooks.runIncremental.tapPromise(exports.PLUGIN_NAME, async (runOptions) => {
79
+ await this._runWebpackWatchAsync(taskSession, heftConfiguration, options, runOptions.requestRun);
80
+ });
81
+ }
82
+ async _getWebpackConfigurationAsync(taskSession, heftConfiguration, options, requestRun) {
83
+ if (this._webpackConfiguration === UNINITIALIZED) {
84
+ // Obtain the webpack configuration by calling into the hook. If undefined
85
+ // is returned, load the default Webpack configuration.
86
+ taskSession.logger.terminal.writeVerboseLine('Attempting to load Webpack configuration via external plugins');
87
+ let webpackConfiguration = await this.accessor.hooks.onLoadConfiguration.promise();
88
+ if (webpackConfiguration === undefined) {
89
+ taskSession.logger.terminal.writeVerboseLine('Attempt to load the default Webpack configuration');
90
+ const configurationLoader = new WebpackConfigurationLoader_1.WebpackConfigurationLoader(taskSession.logger, taskSession.parameters.production, taskSession.parameters.watch && this._isServeMode);
91
+ webpackConfiguration = await configurationLoader.tryLoadWebpackConfigurationAsync(Object.assign(Object.assign({}, options), { taskSession,
92
+ heftConfiguration, loadWebpackAsyncFn: this._loadWebpackAsync.bind(this) }));
93
+ }
94
+ if (webpackConfiguration === false) {
95
+ taskSession.logger.terminal.writeLine('Webpack disabled by external plugin');
96
+ this._webpackConfiguration = undefined;
97
+ }
98
+ else if (webpackConfiguration === undefined ||
99
+ (Array.isArray(webpackConfiguration) && webpackConfiguration.length === 0)) {
100
+ taskSession.logger.terminal.writeLine('No Webpack configuration found');
101
+ this._webpackConfiguration = undefined;
102
+ }
103
+ else {
104
+ if (this.accessor.hooks.onConfigure.isUsed()) {
105
+ // Allow for plugins to customise the configuration
106
+ await this.accessor.hooks.onConfigure.promise(webpackConfiguration);
107
+ }
108
+ if (this.accessor.hooks.onAfterConfigure.isUsed()) {
109
+ // Provide the finalized configuration
110
+ await this.accessor.hooks.onAfterConfigure.promise(webpackConfiguration);
111
+ }
112
+ this._webpackConfiguration = webpackConfiguration;
113
+ if (requestRun) {
114
+ const overrideWatchFSPlugin = new DeferredWatchFileSystem_1.OverrideNodeWatchFSPlugin(requestRun);
115
+ this._watchFileSystems = overrideWatchFSPlugin.fileSystems;
116
+ for (const config of Array.isArray(webpackConfiguration)
117
+ ? webpackConfiguration
118
+ : [webpackConfiguration]) {
119
+ if (!config.plugins) {
120
+ config.plugins = [overrideWatchFSPlugin];
121
+ }
122
+ else {
123
+ config.plugins.unshift(overrideWatchFSPlugin);
124
+ }
125
+ }
126
+ }
127
+ }
128
+ }
129
+ return this._webpackConfiguration;
130
+ }
131
+ async _loadWebpackAsync() {
132
+ if (!this._webpack) {
133
+ // Allow this to fail if webpack is not installed
134
+ this._webpack = await Promise.resolve().then(() => __importStar(require(WEBPACK_PACKAGE_NAME)));
135
+ }
136
+ return this._webpack;
137
+ }
138
+ async _getWebpackCompilerAsync(taskSession, webpackConfiguration) {
139
+ if (!this._webpackCompiler) {
140
+ const webpack = await this._loadWebpackAsync();
141
+ taskSession.logger.terminal.writeLine(`Using Webpack version ${webpack.version}`);
142
+ this._webpackCompiler = Array.isArray(webpackConfiguration)
143
+ ? webpack.default(webpackConfiguration) /* (webpack.Compilation[]) => MultiCompiler */
144
+ : webpack.default(webpackConfiguration); /* (webpack.Compilation) => Compiler */
145
+ }
146
+ return this._webpackCompiler;
147
+ }
148
+ async _runWebpackAsync(taskSession, heftConfiguration, options) {
149
+ this._validateEnvironmentVariable(taskSession);
150
+ if (taskSession.parameters.watch || this._isServeMode) {
151
+ // Should never happen, but just in case
152
+ throw new node_core_library_1.InternalError('Cannot run Webpack in compilation mode when watch mode is enabled');
153
+ }
154
+ // Load the config and compiler, and return if there is no config found
155
+ const webpackConfiguration = await this._getWebpackConfigurationAsync(taskSession, heftConfiguration, options);
156
+ if (!webpackConfiguration) {
157
+ return;
158
+ }
159
+ const compiler = await this._getWebpackCompilerAsync(taskSession, webpackConfiguration);
160
+ taskSession.logger.terminal.writeLine('Running Webpack compilation');
161
+ // Run the webpack compiler
162
+ let stats;
163
+ try {
164
+ stats = await node_core_library_1.LegacyAdapters.convertCallbackToPromise(compiler.run.bind(compiler));
165
+ await node_core_library_1.LegacyAdapters.convertCallbackToPromise(compiler.close.bind(compiler));
166
+ }
167
+ catch (e) {
168
+ taskSession.logger.emitError(e);
169
+ }
170
+ // Emit the errors from the stats object, if present
171
+ if (stats) {
172
+ this._recordErrors(stats, heftConfiguration.buildFolderPath);
173
+ this._emitErrors(taskSession.logger);
174
+ if (this.accessor.hooks.onEmitStats.isUsed()) {
175
+ await this.accessor.hooks.onEmitStats.promise(stats);
176
+ }
177
+ }
178
+ }
179
+ async _runWebpackWatchAsync(taskSession, heftConfiguration, options, requestRun) {
180
+ var _a;
181
+ // Save a handle to the original promise, since the this-scoped promise will be replaced whenever
182
+ // the compilation completes.
183
+ let webpackCompilationDonePromise = this._webpackCompilationDonePromise;
184
+ let isInitial = false;
185
+ if (!this._webpackCompiler) {
186
+ isInitial = true;
187
+ this._validateEnvironmentVariable(taskSession);
188
+ if (!taskSession.parameters.watch) {
189
+ // Should never happen, but just in case
190
+ throw new node_core_library_1.InternalError('Cannot run Webpack in watch mode when compilation mode is enabled');
191
+ }
192
+ // Load the config and compiler, and return if there is no config found
193
+ const webpackConfiguration = await this._getWebpackConfigurationAsync(taskSession, heftConfiguration, options, requestRun);
194
+ if (!webpackConfiguration) {
195
+ return;
196
+ }
197
+ // Get the compiler which will be used for both serve and watch mode
198
+ const compiler = await this._getWebpackCompilerAsync(taskSession, webpackConfiguration);
199
+ // Set up the hook to detect when the watcher completes the watcher compilation. We will also log out
200
+ // errors from the compilation if present from the output stats object.
201
+ this._webpackCompilationDonePromise = new Promise((resolve) => {
202
+ this._webpackCompilationDonePromiseResolveFn = resolve;
203
+ });
204
+ webpackCompilationDonePromise = this._webpackCompilationDonePromise;
205
+ compiler.hooks.done.tap(exports.PLUGIN_NAME, (stats) => {
206
+ this._webpackCompilationDonePromiseResolveFn();
207
+ this._webpackCompilationDonePromise = new Promise((resolve) => {
208
+ this._webpackCompilationDonePromiseResolveFn = resolve;
209
+ });
210
+ if (stats) {
211
+ this._recordErrors(stats, heftConfiguration.buildFolderPath);
212
+ }
213
+ });
214
+ // Determine how we will run the compiler. When serving, we will run the compiler
215
+ // via the webpack-dev-server. Otherwise, we will run the compiler directly.
216
+ if (this._isServeMode) {
217
+ const defaultDevServerOptions = {
218
+ host: 'localhost',
219
+ devMiddleware: {
220
+ publicPath: '/',
221
+ stats: {
222
+ cached: false,
223
+ cachedAssets: false,
224
+ colors: heftConfiguration.terminalProvider.supportsColor
225
+ }
226
+ },
227
+ client: {
228
+ logging: 'info',
229
+ webSocketURL: {
230
+ port: 8080
231
+ }
232
+ },
233
+ port: 8080,
234
+ onListening: (server) => {
235
+ var _a;
236
+ const addressInfo = (_a = server.server) === null || _a === void 0 ? void 0 : _a.address();
237
+ if (addressInfo) {
238
+ const address = typeof addressInfo === 'string' ? addressInfo : `${addressInfo.address}:${addressInfo.port}`;
239
+ taskSession.logger.terminal.writeLine(`Started Webpack Dev Server at https://${address}`);
240
+ }
241
+ }
242
+ };
243
+ // Obtain the devServerOptions from the webpack configuration, and combine with the default options
244
+ let devServerOptions;
245
+ if (Array.isArray(webpackConfiguration)) {
246
+ const filteredDevServerOptions = webpackConfiguration
247
+ .map((configuration) => configuration.devServer)
248
+ .filter((devServer) => !!devServer);
249
+ if (filteredDevServerOptions.length > 1) {
250
+ taskSession.logger.emitWarning(new Error(`Detected multiple webpack devServer configurations, using the first one.`));
251
+ }
252
+ devServerOptions = Object.assign(Object.assign({}, defaultDevServerOptions), filteredDevServerOptions[0]);
253
+ }
254
+ else {
255
+ devServerOptions = Object.assign(Object.assign({}, defaultDevServerOptions), webpackConfiguration.devServer);
256
+ }
257
+ // Add the certificate and key to the devServerOptions if these fields don't already have values
258
+ if (!devServerOptions.server) {
259
+ const certificateManager = new debug_certificate_manager_1.CertificateManager();
260
+ const certificate = await certificateManager.ensureCertificateAsync(true, taskSession.logger.terminal);
261
+ // Update the web socket URL to use the hostname provided by the certificate
262
+ const clientConfiguration = devServerOptions.client;
263
+ const hostname = (_a = certificate.subjectAltNames) === null || _a === void 0 ? void 0 : _a[0];
264
+ if (hostname && typeof clientConfiguration === 'object') {
265
+ const { webSocketURL } = clientConfiguration;
266
+ if (typeof webSocketURL === 'object') {
267
+ clientConfiguration.webSocketURL = Object.assign(Object.assign({}, webSocketURL), { hostname });
268
+ }
269
+ }
270
+ devServerOptions = Object.assign(Object.assign({}, devServerOptions), { server: {
271
+ type: 'https',
272
+ options: {
273
+ minVersion: 'TLSv1.3',
274
+ key: certificate.pemKey,
275
+ cert: certificate.pemCertificate,
276
+ ca: certificate.pemCaCertificate
277
+ }
278
+ } });
279
+ }
280
+ // Since the webpack-dev-server does not return infrastructure errors via a callback like
281
+ // compiler.watch(...), we will need to intercept them and log them ourselves.
282
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
283
+ compiler.hooks.infrastructureLog.tap(exports.PLUGIN_NAME, (name, type, args) => {
284
+ if (name === WEBPACK_DEV_MIDDLEWARE_PACKAGE_NAME && type === 'error') {
285
+ const error = args[0];
286
+ if (error) {
287
+ taskSession.logger.emitError(error);
288
+ }
289
+ }
290
+ return true;
291
+ });
292
+ // The webpack-dev-server package has a design flaw, where merely loading its package will set the
293
+ // WEBPACK_DEV_SERVER environment variable -- even if no APIs are accessed. This environment variable
294
+ // causes incorrect behavior if Heft is not running in serve mode. Thus, we need to be careful to call
295
+ // require() only if Heft is in serve mode.
296
+ taskSession.logger.terminal.writeLine('Starting webpack-dev-server');
297
+ const WebpackDevServer = (await Promise.resolve().then(() => __importStar(require(WEBPACK_DEV_SERVER_PACKAGE_NAME))))
298
+ .default;
299
+ const webpackDevServer = new WebpackDevServer(devServerOptions, compiler);
300
+ await webpackDevServer.start();
301
+ }
302
+ else {
303
+ // Create the watcher. Compilation will start immediately after invoking watch().
304
+ taskSession.logger.terminal.writeLine('Starting Webpack watcher');
305
+ compiler.watch({}, (error) => {
306
+ if (error) {
307
+ taskSession.logger.emitError(error);
308
+ }
309
+ });
310
+ }
311
+ }
312
+ let hasChanges = true;
313
+ if (!isInitial && this._watchFileSystems) {
314
+ hasChanges = false;
315
+ for (const watchFileSystem of this._watchFileSystems) {
316
+ hasChanges = watchFileSystem.flush() || hasChanges;
317
+ }
318
+ }
319
+ // Resume the compilation, wait for the compilation to complete, then suspend the watchers until the
320
+ // next iteration. Even if there are no changes, the promise should resolve since resuming from a
321
+ // suspended state invalidates the state of the watcher.
322
+ if (hasChanges) {
323
+ taskSession.logger.terminal.writeLine('Running incremental Webpack compilation');
324
+ await webpackCompilationDonePromise;
325
+ }
326
+ else {
327
+ taskSession.logger.terminal.writeLine('Webpack has not detected changes. Listing previous diagnostics.');
328
+ }
329
+ this._emitErrors(taskSession.logger);
330
+ }
331
+ _validateEnvironmentVariable(taskSession) {
332
+ if (!this._isServeMode && process.env[WEBPACK_DEV_SERVER_ENV_VAR_NAME]) {
333
+ taskSession.logger.emitWarning(new Error(`The "${WEBPACK_DEV_SERVER_ENV_VAR_NAME}" environment variable is set, ` +
334
+ 'which will cause problems when webpack is not running in serve mode. ' +
335
+ `(Did a dependency inadvertently load the "${WEBPACK_DEV_SERVER_PACKAGE_NAME}" package?)`));
336
+ }
337
+ }
338
+ _emitErrors(logger) {
339
+ for (const warning of this._warnings) {
340
+ logger.emitWarning(warning);
341
+ }
342
+ for (const error of this._errors) {
343
+ logger.emitError(error);
344
+ }
345
+ }
346
+ _recordErrors(stats, buildFolderPath) {
347
+ const errors = this._errors;
348
+ const warnings = this._warnings;
349
+ errors.length = 0;
350
+ warnings.length = 0;
351
+ if (stats.hasErrors() || stats.hasWarnings()) {
352
+ const serializedStats = [stats.toJson('errors-warnings')];
353
+ for (const compilationStats of serializedStats) {
354
+ if (compilationStats.warnings) {
355
+ for (const warning of compilationStats.warnings) {
356
+ warnings.push(this._normalizeError(buildFolderPath, warning));
357
+ }
358
+ }
359
+ if (compilationStats.errors) {
360
+ for (const error of compilationStats.errors) {
361
+ errors.push(this._normalizeError(buildFolderPath, error));
362
+ }
363
+ }
364
+ if (compilationStats.children) {
365
+ for (const child of compilationStats.children) {
366
+ serializedStats.push(child);
367
+ }
368
+ }
369
+ }
370
+ }
371
+ }
372
+ _normalizeError(buildFolderPath, error) {
373
+ if (error instanceof Error) {
374
+ return error;
375
+ }
376
+ else if (error.moduleIdentifier) {
377
+ let lineNumber;
378
+ let columnNumber;
379
+ if (error.loc) {
380
+ // Format of "<line>:<columnStart>-<columnEnd>"
381
+ // https://webpack.js.org/api/stats/#errors-and-warnings
382
+ const [lineNumberRaw, columnRangeRaw] = error.loc.split(':');
383
+ const [startColumnRaw] = columnRangeRaw.split('-');
384
+ if (lineNumberRaw) {
385
+ lineNumber = parseInt(lineNumberRaw, 10);
386
+ if (isNaN(lineNumber)) {
387
+ lineNumber = undefined;
388
+ }
389
+ }
390
+ if (startColumnRaw) {
391
+ columnNumber = parseInt(startColumnRaw, 10);
392
+ if (isNaN(columnNumber)) {
393
+ columnNumber = undefined;
394
+ }
395
+ }
396
+ }
397
+ return new node_core_library_1.FileError(error.message, {
398
+ absolutePath: error.moduleIdentifier,
399
+ projectFolder: buildFolderPath,
400
+ line: lineNumber,
401
+ column: columnNumber
402
+ });
403
+ }
404
+ else {
405
+ return new Error(error.message);
406
+ }
407
+ }
408
+ }
409
+ exports.default = Webpack5Plugin;
410
+ //# sourceMappingURL=Webpack5Plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Webpack5Plugin.js","sourceRoot":"","sources":["../src/Webpack5Plugin.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;;;;;;;;;;;;;;;;;;;;;;;;AAM3D,qCAAkF;AAElF,oFAA6F;AAC7F,oEAAwF;AAWxF,6EAA0E;AAC1E,uEAA+F;AAO/F;;GAEG;AACU,QAAA,WAAW,GAAsB,iBAAiB,CAAC;AAChE,MAAM,yBAAyB,GAAc,SAAS,CAAC;AACvD,MAAM,oBAAoB,GAAc,SAAS,CAAC;AAClD,MAAM,+BAA+B,GAAyB,oBAAoB,CAAC;AACnF,MAAM,+BAA+B,GAAyB,oBAAoB,CAAC;AACnF,MAAM,mCAAmC,GAA6B,wBAAwB,CAAC;AAC/F,MAAM,aAAa,GAAoB,eAAe,CAAC;AAEvD;;GAEG;AACH,MAAqB,cAAc;IAAnC;QAEU,iBAAY,GAAY,KAAK,CAAC;QAG9B,0BAAqB,GAA6D,aAAa,CAAC;QAKhG,cAAS,GAAY,EAAE,CAAC;QACxB,YAAO,GAAY,EAAE,CAAC;IAwchC,CAAC;IAtcC,IAAW,QAAQ;QACjB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YACnB,IAAI,CAAC,SAAS,GAAG;gBACf,KAAK,EAAE;oBACL,mBAAmB,EAAE,IAAI,6BAAmB,EAAE;oBAC9C,WAAW,EAAE,IAAI,yBAAe,CAAC,CAAC,sBAAsB,CAAC,CAAC;oBAC1D,gBAAgB,EAAE,IAAI,2BAAiB,CAAC,CAAC,sBAAsB,CAAC,CAAC;oBACjE,WAAW,EAAE,IAAI,2BAAiB,CAAC,CAAC,cAAc,CAAC,CAAC;iBACrD;gBACD,UAAU,EAAE;oBACV,WAAW,EAAE,IAAI,CAAC,YAAY;iBAC/B;aACF,CAAC;SACH;QACD,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAEM,KAAK,CACV,WAA6B,EAC7B,iBAAoC,EACpC,OAA8B;QAE9B,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC,UAAU,CAAC,gBAAgB,CAAC,yBAAyB,CAAC,CAAC,KAAK,CAAC;QAC7F,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY,EAAE;YACtD,MAAM,IAAI,KAAK,CACb,OAAO,IAAI,CAAC,SAAS,CACnB,yBAAyB,CAC1B,0DAA0D,CAC5D,CAAC;SACH;QAED,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,mBAAW,EAAE,KAAK,EAAE,UAAmC,EAAE,EAAE;YAC1F,MAAM,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,iBAAiB,EAAE,OAAO,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CACzC,mBAAW,EACX,KAAK,EAAE,UAA8C,EAAE,EAAE;YACvD,MAAM,IAAI,CAAC,qBAAqB,CAAC,WAAW,EAAE,iBAAiB,EAAE,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;QACnG,CAAC,CACF,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,6BAA6B,CACzC,WAA6B,EAC7B,iBAAoC,EACpC,OAA8B,EAC9B,UAAuB;QAEvB,IAAI,IAAI,CAAC,qBAAqB,KAAK,aAAa,EAAE;YAChD,0EAA0E;YAC1E,uDAAuD;YACvD,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAC1C,+DAA+D,CAChE,CAAC;YACF,IAAI,oBAAoB,GACtB,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,mBAAmB,CAAC,OAAO,EAAE,CAAC;YAC1D,IAAI,oBAAoB,KAAK,SAAS,EAAE;gBACtC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,mDAAmD,CAAC,CAAC;gBAClG,MAAM,mBAAmB,GAA+B,IAAI,uDAA0B,CACpF,WAAW,CAAC,MAAM,EAClB,WAAW,CAAC,UAAU,CAAC,UAAU,EACjC,WAAW,CAAC,UAAU,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY,CAClD,CAAC;gBACF,oBAAoB,GAAG,MAAM,mBAAmB,CAAC,gCAAgC,iCAC5E,OAAO,KACV,WAAW;oBACX,iBAAiB,EACjB,kBAAkB,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IACrD,CAAC;aACJ;YAED,IAAI,oBAAoB,KAAK,KAAK,EAAE;gBAClC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,qCAAqC,CAAC,CAAC;gBAC7E,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC;aACxC;iBAAM,IACL,oBAAoB,KAAK,SAAS;gBAClC,CAAC,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAC,IAAI,oBAAoB,CAAC,MAAM,KAAK,CAAC,CAAC,EAC1E;gBACA,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;gBACxE,IAAI,CAAC,qBAAqB,GAAG,SAAS,CAAC;aACxC;iBAAM;gBACL,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE;oBAC5C,mDAAmD;oBACnD,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;iBACrE;gBACD,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,EAAE,EAAE;oBACjD,sCAAsC;oBACtC,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;iBAC1E;gBACD,IAAI,CAAC,qBAAqB,GAAG,oBAAoB,CAAC;gBAElD,IAAI,UAAU,EAAE;oBACd,MAAM,qBAAqB,GAA8B,IAAI,mDAAyB,CAAC,UAAU,CAAC,CAAC;oBACnG,IAAI,CAAC,iBAAiB,GAAG,qBAAqB,CAAC,WAAW,CAAC;oBAC3D,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAC;wBACtD,CAAC,CAAC,oBAAoB;wBACtB,CAAC,CAAC,CAAC,oBAAoB,CAAC,EAAE;wBAC1B,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;4BACnB,MAAM,CAAC,OAAO,GAAG,CAAC,qBAAqB,CAAC,CAAC;yBAC1C;6BAAM;4BACL,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;yBAC/C;qBACF;iBACF;aACF;SACF;QACD,OAAO,IAAI,CAAC,qBAAqB,CAAC;IACpC,CAAC;IAEO,KAAK,CAAC,iBAAiB;QAC7B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAClB,iDAAiD;YACjD,IAAI,CAAC,QAAQ,GAAG,wDAAa,oBAAoB,GAAC,CAAC;SACpD;QACD,OAAO,IAAI,CAAC,QAAS,CAAC;IACxB,CAAC;IAEO,KAAK,CAAC,wBAAwB,CACpC,WAA6B,EAC7B,oBAA2C;QAE3C,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;YAC1B,MAAM,OAAO,GAAoB,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAChE,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,yBAAyB,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;YAClF,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAC;gBACzD,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,8CAA8C;gBACtF,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,uCAAuC;SACnF;QACD,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAC5B,WAA6B,EAC7B,iBAAoC,EACpC,OAA8B;QAE9B,IAAI,CAAC,4BAA4B,CAAC,WAAW,CAAC,CAAC;QAC/C,IAAI,WAAW,CAAC,UAAU,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY,EAAE;YACrD,wCAAwC;YACxC,MAAM,IAAI,iCAAa,CAAC,mEAAmE,CAAC,CAAC;SAC9F;QAED,uEAAuE;QACvE,MAAM,oBAAoB,GAAsC,MAAM,IAAI,CAAC,6BAA6B,CACtG,WAAW,EACX,iBAAiB,EACjB,OAAO,CACR,CAAC;QACF,IAAI,CAAC,oBAAoB,EAAE;YACzB,OAAO;SACR;QACD,MAAM,QAAQ,GAA+C,MAAM,IAAI,CAAC,wBAAwB,CAC9F,WAAW,EACX,oBAAoB,CACrB,CAAC;QACF,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;QAErE,2BAA2B;QAC3B,IAAI,KAAuD,CAAC;QAC5D,IAAI;YACF,KAAK,GAAG,MAAM,kCAAc,CAAC,wBAAwB,CAClD,QAA8B,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CACnD,CAAC;YACF,MAAM,kCAAc,CAAC,wBAAwB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;SAC9E;QAAC,OAAO,CAAC,EAAE;YACV,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAU,CAAC,CAAC;SAC1C;QAED,oDAAoD;QACpD,IAAI,KAAK,EAAE;YACT,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,iBAAiB,CAAC,eAAe,CAAC,CAAC;YAC7D,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YACrC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE;gBAC5C,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;aACtD;SACF;IACH,CAAC;IAEO,KAAK,CAAC,qBAAqB,CACjC,WAA6B,EAC7B,iBAAoC,EACpC,OAA8B,EAC9B,UAAsB;;QAEtB,iGAAiG;QACjG,6BAA6B;QAC7B,IAAI,6BAA6B,GAA8B,IAAI,CAAC,8BAA8B,CAAC;QAEnG,IAAI,SAAS,GAAY,KAAK,CAAC;QAE/B,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;YAC1B,SAAS,GAAG,IAAI,CAAC;YACjB,IAAI,CAAC,4BAA4B,CAAC,WAAW,CAAC,CAAC;YAC/C,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,EAAE;gBACjC,wCAAwC;gBACxC,MAAM,IAAI,iCAAa,CAAC,mEAAmE,CAAC,CAAC;aAC9F;YAED,uEAAuE;YACvE,MAAM,oBAAoB,GACxB,MAAM,IAAI,CAAC,6BAA6B,CAAC,WAAW,EAAE,iBAAiB,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;YAChG,IAAI,CAAC,oBAAoB,EAAE;gBACzB,OAAO;aACR;YAED,oEAAoE;YACpE,MAAM,QAAQ,GAA+C,MAAM,IAAI,CAAC,wBAAwB,CAC9F,WAAW,EACX,oBAAoB,CACrB,CAAC;YAEF,qGAAqG;YACrG,uEAAuE;YACvE,IAAI,CAAC,8BAA8B,GAAG,IAAI,OAAO,CAAC,CAAC,OAAmB,EAAE,EAAE;gBACxE,IAAI,CAAC,uCAAuC,GAAG,OAAO,CAAC;YACzD,CAAC,CAAC,CAAC;YACH,6BAA6B,GAAG,IAAI,CAAC,8BAA8B,CAAC;YACpE,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,mBAAW,EAAE,CAAC,KAA4C,EAAE,EAAE;gBACpF,IAAI,CAAC,uCAAwC,EAAE,CAAC;gBAChD,IAAI,CAAC,8BAA8B,GAAG,IAAI,OAAO,CAAC,CAAC,OAAmB,EAAE,EAAE;oBACxE,IAAI,CAAC,uCAAuC,GAAG,OAAO,CAAC;gBACzD,CAAC,CAAC,CAAC;gBAEH,IAAI,KAAK,EAAE;oBACT,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,iBAAiB,CAAC,eAAe,CAAC,CAAC;iBAC9D;YACH,CAAC,CAAC,CAAC;YAEH,iFAAiF;YACjF,4EAA4E;YAC5E,IAAI,IAAI,CAAC,YAAY,EAAE;gBACrB,MAAM,uBAAuB,GAAoC;oBAC/D,IAAI,EAAE,WAAW;oBACjB,aAAa,EAAE;wBACb,UAAU,EAAE,GAAG;wBACf,KAAK,EAAE;4BACL,MAAM,EAAE,KAAK;4BACb,YAAY,EAAE,KAAK;4BACnB,MAAM,EAAE,iBAAiB,CAAC,gBAAgB,CAAC,aAAa;yBACzD;qBACF;oBACD,MAAM,EAAE;wBACN,OAAO,EAAE,MAAM;wBACf,YAAY,EAAE;4BACZ,IAAI,EAAE,IAAI;yBACX;qBACF;oBACD,IAAI,EAAE,IAAI;oBACV,WAAW,EAAE,CAAC,MAAyB,EAAE,EAAE;;wBACzC,MAAM,WAAW,GAAqC,MAAA,MAAM,CAAC,MAAM,0CAAE,OAAO,EAAiB,CAAC;wBAC9F,IAAI,WAAW,EAAE;4BACf,MAAM,OAAO,GACX,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,OAAO,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC;4BAC/F,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,yCAAyC,OAAO,EAAE,CAAC,CAAC;yBAC3F;oBACH,CAAC;iBACF,CAAC;gBAEF,mGAAmG;gBACnG,IAAI,gBAAiD,CAAC;gBACtD,IAAI,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE;oBACvC,MAAM,wBAAwB,GAAsC,oBAAoB;yBACrF,GAAG,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC;yBAC/C,MAAM,CAAC,CAAC,SAAS,EAAgD,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;oBACpF,IAAI,wBAAwB,CAAC,MAAM,GAAG,CAAC,EAAE;wBACvC,WAAW,CAAC,MAAM,CAAC,WAAW,CAC5B,IAAI,KAAK,CAAC,0EAA0E,CAAC,CACtF,CAAC;qBACH;oBACD,gBAAgB,mCAAQ,uBAAuB,GAAK,wBAAwB,CAAC,CAAC,CAAC,CAAE,CAAC;iBACnF;qBAAM;oBACL,gBAAgB,mCAAQ,uBAAuB,GAAK,oBAAoB,CAAC,SAAS,CAAE,CAAC;iBACtF;gBAED,gGAAgG;gBAChG,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE;oBAC5B,MAAM,kBAAkB,GAAuB,IAAI,8CAAkB,EAAE,CAAC;oBACxE,MAAM,WAAW,GAAiB,MAAM,kBAAkB,CAAC,sBAAsB,CAC/E,IAAI,EACJ,WAAW,CAAC,MAAM,CAAC,QAAQ,CAC5B,CAAC;oBAEF,4EAA4E;oBAC5E,MAAM,mBAAmB,GAA8C,gBAAgB,CAAC,MAAM,CAAC;oBAC/F,MAAM,QAAQ,GAAuB,MAAA,WAAW,CAAC,eAAe,0CAAG,CAAC,CAAC,CAAC;oBACtE,IAAI,QAAQ,IAAI,OAAO,mBAAmB,KAAK,QAAQ,EAAE;wBACvD,MAAM,EAAE,YAAY,EAAE,GAAG,mBAAmB,CAAC;wBAC7C,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE;4BACpC,mBAAmB,CAAC,YAAY,mCAC3B,YAAY,KACf,QAAQ,GACT,CAAC;yBACH;qBACF;oBAED,gBAAgB,mCACX,gBAAgB,KACnB,MAAM,EAAE;4BACN,IAAI,EAAE,OAAO;4BACb,OAAO,EAAE;gCACP,UAAU,EAAE,SAAS;gCACrB,GAAG,EAAE,WAAW,CAAC,MAAM;gCACvB,IAAI,EAAE,WAAW,CAAC,cAAc;gCAChC,EAAE,EAAE,WAAW,CAAC,gBAAgB;6BACjC;yBACF,GACF,CAAC;iBACH;gBAED,yFAAyF;gBACzF,8EAA8E;gBAC9E,8DAA8D;gBAC9D,QAAQ,CAAC,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,mBAAW,EAAE,CAAC,IAAY,EAAE,IAAY,EAAE,IAAW,EAAE,EAAE;oBAC5F,IAAI,IAAI,KAAK,mCAAmC,IAAI,IAAI,KAAK,OAAO,EAAE;wBACpE,MAAM,KAAK,GAAsB,IAAI,CAAC,CAAC,CAAC,CAAC;wBACzC,IAAI,KAAK,EAAE;4BACT,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;yBACrC;qBACF;oBACD,OAAO,IAAI,CAAC;gBACd,CAAC,CAAC,CAAC;gBAEH,kGAAkG;gBAClG,qGAAqG;gBACrG,sGAAsG;gBACtG,2CAA2C;gBAC3C,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;gBACrE,MAAM,gBAAgB,GAA6B,CAAC,wDAAa,+BAA+B,GAAC,CAAC;qBAC/F,OAAO,CAAC;gBACX,MAAM,gBAAgB,GAAsB,IAAI,gBAAgB,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;gBAC7F,MAAM,gBAAgB,CAAC,KAAK,EAAE,CAAC;aAChC;iBAAM;gBACL,iFAAiF;gBACjF,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;gBAClE,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAoB,EAAE,EAAE;oBAC1C,IAAI,KAAK,EAAE;wBACT,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;qBACrC;gBACH,CAAC,CAAC,CAAC;aACJ;SACF;QAED,IAAI,UAAU,GAAY,IAAI,CAAC;QAC/B,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,iBAAiB,EAAE;YACxC,UAAU,GAAG,KAAK,CAAC;YACnB,KAAK,MAAM,eAAe,IAAI,IAAI,CAAC,iBAAiB,EAAE;gBACpD,UAAU,GAAG,eAAe,CAAC,KAAK,EAAE,IAAI,UAAU,CAAC;aACpD;SACF;QAED,oGAAoG;QACpG,iGAAiG;QACjG,wDAAwD;QACxD,IAAI,UAAU,EAAE;YACd,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,yCAAyC,CAAC,CAAC;YACjF,MAAM,6BAA6B,CAAC;SACrC;aAAM;YACL,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CACnC,iEAAiE,CAClE,CAAC;SACH;QAED,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAEO,4BAA4B,CAAC,WAA6B;QAChE,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,EAAE;YACtE,WAAW,CAAC,MAAM,CAAC,WAAW,CAC5B,IAAI,KAAK,CACP,QAAQ,+BAA+B,iCAAiC;gBACtE,uEAAuE;gBACvE,6CAA6C,+BAA+B,aAAa,CAC5F,CACF,CAAC;SACH;IACH,CAAC;IAEO,WAAW,CAAC,MAAqB;QACvC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE;YACpC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;SAC7B;QACD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE;YAChC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;SACzB;IACH,CAAC;IAEO,aAAa,CAAC,KAA2C,EAAE,eAAuB;QACxF,MAAM,MAAM,GAAY,IAAI,CAAC,OAAO,CAAC;QACrC,MAAM,QAAQ,GAAY,IAAI,CAAC,SAAS,CAAC;QAEzC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QAClB,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;QAEpB,IAAI,KAAK,CAAC,SAAS,EAAE,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE;YAC5C,MAAM,eAAe,GAAgC,CAAC,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC;YAEvF,KAAK,MAAM,gBAAgB,IAAI,eAAe,EAAE;gBAC9C,IAAI,gBAAgB,CAAC,QAAQ,EAAE;oBAC7B,KAAK,MAAM,OAAO,IAAI,gBAAgB,CAAC,QAAQ,EAAE;wBAC/C,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC;qBAC/D;iBACF;gBAED,IAAI,gBAAgB,CAAC,MAAM,EAAE;oBAC3B,KAAK,MAAM,KAAK,IAAI,gBAAgB,CAAC,MAAM,EAAE;wBAC3C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC,CAAC;qBAC3D;iBACF;gBAED,IAAI,gBAAgB,CAAC,QAAQ,EAAE;oBAC7B,KAAK,MAAM,KAAK,IAAI,gBAAgB,CAAC,QAAQ,EAAE;wBAC7C,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;qBAC7B;iBACF;aACF;SACF;IACH,CAAC;IAEO,eAAe,CAAC,eAAuB,EAAE,KAA0B;QACzE,IAAI,KAAK,YAAY,KAAK,EAAE;YAC1B,OAAO,KAAK,CAAC;SACd;aAAM,IAAI,KAAK,CAAC,gBAAgB,EAAE;YACjC,IAAI,UAA8B,CAAC;YACnC,IAAI,YAAgC,CAAC;YACrC,IAAI,KAAK,CAAC,GAAG,EAAE;gBACb,+CAA+C;gBAC/C,wDAAwD;gBACxD,MAAM,CAAC,aAAa,EAAE,cAAc,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC7D,MAAM,CAAC,cAAc,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACnD,IAAI,aAAa,EAAE;oBACjB,UAAU,GAAG,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;oBACzC,IAAI,KAAK,CAAC,UAAU,CAAC,EAAE;wBACrB,UAAU,GAAG,SAAS,CAAC;qBACxB;iBACF;gBACD,IAAI,cAAc,EAAE;oBAClB,YAAY,GAAG,QAAQ,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;oBAC5C,IAAI,KAAK,CAAC,YAAY,CAAC,EAAE;wBACvB,YAAY,GAAG,SAAS,CAAC;qBAC1B;iBACF;aACF;YAED,OAAO,IAAI,6BAAS,CAAC,KAAK,CAAC,OAAO,EAAE;gBAClC,YAAY,EAAE,KAAK,CAAC,gBAAgB;gBACpC,aAAa,EAAE,eAAe;gBAC9B,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,YAAY;aACrB,CAAC,CAAC;SACJ;aAAM;YACL,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;SACjC;IACH,CAAC;CACF;AAndD,iCAmdC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { AddressInfo } from 'net';\n\nimport type * as TWebpack from 'webpack';\nimport type TWebpackDevServer from 'webpack-dev-server';\nimport { AsyncParallelHook, AsyncSeriesBailHook, AsyncSeriesHook } from 'tapable';\n\nimport { CertificateManager, type ICertificate } from '@rushstack/debug-certificate-manager';\nimport { FileError, InternalError, LegacyAdapters } from '@rushstack/node-core-library';\nimport type {\n HeftConfiguration,\n IHeftTaskSession,\n IHeftTaskPlugin,\n IHeftTaskRunHookOptions,\n IScopedLogger,\n IHeftTaskRunIncrementalHookOptions\n} from '@rushstack/heft';\n\nimport type { IWebpackConfiguration, IWebpackPluginAccessor } from './shared';\nimport { WebpackConfigurationLoader } from './WebpackConfigurationLoader';\nimport { DeferredWatchFileSystem, OverrideNodeWatchFSPlugin } from './DeferredWatchFileSystem';\n\nexport interface IWebpackPluginOptions {\n devConfigurationPath: string | undefined;\n configurationPath: string | undefined;\n}\n\n/**\n * @public\n */\nexport const PLUGIN_NAME: 'webpack5-plugin' = 'webpack5-plugin';\nconst SERVE_PARAMETER_LONG_NAME: '--serve' = '--serve';\nconst WEBPACK_PACKAGE_NAME: 'webpack' = 'webpack';\nconst WEBPACK_DEV_SERVER_PACKAGE_NAME: 'webpack-dev-server' = 'webpack-dev-server';\nconst WEBPACK_DEV_SERVER_ENV_VAR_NAME: 'WEBPACK_DEV_SERVER' = 'WEBPACK_DEV_SERVER';\nconst WEBPACK_DEV_MIDDLEWARE_PACKAGE_NAME: 'webpack-dev-middleware' = 'webpack-dev-middleware';\nconst UNINITIALIZED: 'UNINITIALIZED' = 'UNINITIALIZED';\n\n/**\n * @internal\n */\nexport default class Webpack5Plugin implements IHeftTaskPlugin<IWebpackPluginOptions> {\n private _accessor: IWebpackPluginAccessor | undefined;\n private _isServeMode: boolean = false;\n private _webpack: typeof TWebpack | undefined;\n private _webpackCompiler: TWebpack.Compiler | TWebpack.MultiCompiler | undefined;\n private _webpackConfiguration: IWebpackConfiguration | undefined | typeof UNINITIALIZED = UNINITIALIZED;\n private _webpackCompilationDonePromise: Promise<void> | undefined;\n private _webpackCompilationDonePromiseResolveFn: (() => void) | undefined;\n private _watchFileSystems: Set<DeferredWatchFileSystem> | undefined;\n\n private _warnings: Error[] = [];\n private _errors: Error[] = [];\n\n public get accessor(): IWebpackPluginAccessor {\n if (!this._accessor) {\n this._accessor = {\n hooks: {\n onLoadConfiguration: new AsyncSeriesBailHook(),\n onConfigure: new AsyncSeriesHook(['webpackConfiguration']),\n onAfterConfigure: new AsyncParallelHook(['webpackConfiguration']),\n onEmitStats: new AsyncParallelHook(['webpackStats'])\n },\n parameters: {\n isServeMode: this._isServeMode\n }\n };\n }\n return this._accessor;\n }\n\n public apply(\n taskSession: IHeftTaskSession,\n heftConfiguration: HeftConfiguration,\n options: IWebpackPluginOptions\n ): void {\n this._isServeMode = taskSession.parameters.getFlagParameter(SERVE_PARAMETER_LONG_NAME).value;\n if (!taskSession.parameters.watch && this._isServeMode) {\n throw new Error(\n `The ${JSON.stringify(\n SERVE_PARAMETER_LONG_NAME\n )} parameter is only available when running in watch mode.`\n );\n }\n\n taskSession.hooks.run.tapPromise(PLUGIN_NAME, async (runOptions: IHeftTaskRunHookOptions) => {\n await this._runWebpackAsync(taskSession, heftConfiguration, options);\n });\n\n taskSession.hooks.runIncremental.tapPromise(\n PLUGIN_NAME,\n async (runOptions: IHeftTaskRunIncrementalHookOptions) => {\n await this._runWebpackWatchAsync(taskSession, heftConfiguration, options, runOptions.requestRun);\n }\n );\n }\n\n private async _getWebpackConfigurationAsync(\n taskSession: IHeftTaskSession,\n heftConfiguration: HeftConfiguration,\n options: IWebpackPluginOptions,\n requestRun?: () => void\n ): Promise<IWebpackConfiguration | undefined> {\n if (this._webpackConfiguration === UNINITIALIZED) {\n // Obtain the webpack configuration by calling into the hook. If undefined\n // is returned, load the default Webpack configuration.\n taskSession.logger.terminal.writeVerboseLine(\n 'Attempting to load Webpack configuration via external plugins'\n );\n let webpackConfiguration: IWebpackConfiguration | false | undefined =\n await this.accessor.hooks.onLoadConfiguration.promise();\n if (webpackConfiguration === undefined) {\n taskSession.logger.terminal.writeVerboseLine('Attempt to load the default Webpack configuration');\n const configurationLoader: WebpackConfigurationLoader = new WebpackConfigurationLoader(\n taskSession.logger,\n taskSession.parameters.production,\n taskSession.parameters.watch && this._isServeMode\n );\n webpackConfiguration = await configurationLoader.tryLoadWebpackConfigurationAsync({\n ...options,\n taskSession,\n heftConfiguration,\n loadWebpackAsyncFn: this._loadWebpackAsync.bind(this)\n });\n }\n\n if (webpackConfiguration === false) {\n taskSession.logger.terminal.writeLine('Webpack disabled by external plugin');\n this._webpackConfiguration = undefined;\n } else if (\n webpackConfiguration === undefined ||\n (Array.isArray(webpackConfiguration) && webpackConfiguration.length === 0)\n ) {\n taskSession.logger.terminal.writeLine('No Webpack configuration found');\n this._webpackConfiguration = undefined;\n } else {\n if (this.accessor.hooks.onConfigure.isUsed()) {\n // Allow for plugins to customise the configuration\n await this.accessor.hooks.onConfigure.promise(webpackConfiguration);\n }\n if (this.accessor.hooks.onAfterConfigure.isUsed()) {\n // Provide the finalized configuration\n await this.accessor.hooks.onAfterConfigure.promise(webpackConfiguration);\n }\n this._webpackConfiguration = webpackConfiguration;\n\n if (requestRun) {\n const overrideWatchFSPlugin: OverrideNodeWatchFSPlugin = new OverrideNodeWatchFSPlugin(requestRun);\n this._watchFileSystems = overrideWatchFSPlugin.fileSystems;\n for (const config of Array.isArray(webpackConfiguration)\n ? webpackConfiguration\n : [webpackConfiguration]) {\n if (!config.plugins) {\n config.plugins = [overrideWatchFSPlugin];\n } else {\n config.plugins.unshift(overrideWatchFSPlugin);\n }\n }\n }\n }\n }\n return this._webpackConfiguration;\n }\n\n private async _loadWebpackAsync(): Promise<typeof TWebpack> {\n if (!this._webpack) {\n // Allow this to fail if webpack is not installed\n this._webpack = await import(WEBPACK_PACKAGE_NAME);\n }\n return this._webpack!;\n }\n\n private async _getWebpackCompilerAsync(\n taskSession: IHeftTaskSession,\n webpackConfiguration: IWebpackConfiguration\n ): Promise<TWebpack.Compiler | TWebpack.MultiCompiler> {\n if (!this._webpackCompiler) {\n const webpack: typeof TWebpack = await this._loadWebpackAsync();\n taskSession.logger.terminal.writeLine(`Using Webpack version ${webpack.version}`);\n this._webpackCompiler = Array.isArray(webpackConfiguration)\n ? webpack.default(webpackConfiguration) /* (webpack.Compilation[]) => MultiCompiler */\n : webpack.default(webpackConfiguration); /* (webpack.Compilation) => Compiler */\n }\n return this._webpackCompiler;\n }\n\n private async _runWebpackAsync(\n taskSession: IHeftTaskSession,\n heftConfiguration: HeftConfiguration,\n options: IWebpackPluginOptions\n ): Promise<void> {\n this._validateEnvironmentVariable(taskSession);\n if (taskSession.parameters.watch || this._isServeMode) {\n // Should never happen, but just in case\n throw new InternalError('Cannot run Webpack in compilation mode when watch mode is enabled');\n }\n\n // Load the config and compiler, and return if there is no config found\n const webpackConfiguration: IWebpackConfiguration | undefined = await this._getWebpackConfigurationAsync(\n taskSession,\n heftConfiguration,\n options\n );\n if (!webpackConfiguration) {\n return;\n }\n const compiler: TWebpack.Compiler | TWebpack.MultiCompiler = await this._getWebpackCompilerAsync(\n taskSession,\n webpackConfiguration\n );\n taskSession.logger.terminal.writeLine('Running Webpack compilation');\n\n // Run the webpack compiler\n let stats: TWebpack.Stats | TWebpack.MultiStats | undefined;\n try {\n stats = await LegacyAdapters.convertCallbackToPromise(\n (compiler as TWebpack.Compiler).run.bind(compiler)\n );\n await LegacyAdapters.convertCallbackToPromise(compiler.close.bind(compiler));\n } catch (e) {\n taskSession.logger.emitError(e as Error);\n }\n\n // Emit the errors from the stats object, if present\n if (stats) {\n this._recordErrors(stats, heftConfiguration.buildFolderPath);\n this._emitErrors(taskSession.logger);\n if (this.accessor.hooks.onEmitStats.isUsed()) {\n await this.accessor.hooks.onEmitStats.promise(stats);\n }\n }\n }\n\n private async _runWebpackWatchAsync(\n taskSession: IHeftTaskSession,\n heftConfiguration: HeftConfiguration,\n options: IWebpackPluginOptions,\n requestRun: () => void\n ): Promise<void> {\n // Save a handle to the original promise, since the this-scoped promise will be replaced whenever\n // the compilation completes.\n let webpackCompilationDonePromise: Promise<void> | undefined = this._webpackCompilationDonePromise;\n\n let isInitial: boolean = false;\n\n if (!this._webpackCompiler) {\n isInitial = true;\n this._validateEnvironmentVariable(taskSession);\n if (!taskSession.parameters.watch) {\n // Should never happen, but just in case\n throw new InternalError('Cannot run Webpack in watch mode when compilation mode is enabled');\n }\n\n // Load the config and compiler, and return if there is no config found\n const webpackConfiguration: IWebpackConfiguration | undefined =\n await this._getWebpackConfigurationAsync(taskSession, heftConfiguration, options, requestRun);\n if (!webpackConfiguration) {\n return;\n }\n\n // Get the compiler which will be used for both serve and watch mode\n const compiler: TWebpack.Compiler | TWebpack.MultiCompiler = await this._getWebpackCompilerAsync(\n taskSession,\n webpackConfiguration\n );\n\n // Set up the hook to detect when the watcher completes the watcher compilation. We will also log out\n // errors from the compilation if present from the output stats object.\n this._webpackCompilationDonePromise = new Promise((resolve: () => void) => {\n this._webpackCompilationDonePromiseResolveFn = resolve;\n });\n webpackCompilationDonePromise = this._webpackCompilationDonePromise;\n compiler.hooks.done.tap(PLUGIN_NAME, (stats?: TWebpack.Stats | TWebpack.MultiStats) => {\n this._webpackCompilationDonePromiseResolveFn!();\n this._webpackCompilationDonePromise = new Promise((resolve: () => void) => {\n this._webpackCompilationDonePromiseResolveFn = resolve;\n });\n\n if (stats) {\n this._recordErrors(stats, heftConfiguration.buildFolderPath);\n }\n });\n\n // Determine how we will run the compiler. When serving, we will run the compiler\n // via the webpack-dev-server. Otherwise, we will run the compiler directly.\n if (this._isServeMode) {\n const defaultDevServerOptions: TWebpackDevServer.Configuration = {\n host: 'localhost',\n devMiddleware: {\n publicPath: '/',\n stats: {\n cached: false,\n cachedAssets: false,\n colors: heftConfiguration.terminalProvider.supportsColor\n }\n },\n client: {\n logging: 'info',\n webSocketURL: {\n port: 8080\n }\n },\n port: 8080,\n onListening: (server: TWebpackDevServer) => {\n const addressInfo: AddressInfo | string | undefined = server.server?.address() as AddressInfo;\n if (addressInfo) {\n const address: string =\n typeof addressInfo === 'string' ? addressInfo : `${addressInfo.address}:${addressInfo.port}`;\n taskSession.logger.terminal.writeLine(`Started Webpack Dev Server at https://${address}`);\n }\n }\n };\n\n // Obtain the devServerOptions from the webpack configuration, and combine with the default options\n let devServerOptions: TWebpackDevServer.Configuration;\n if (Array.isArray(webpackConfiguration)) {\n const filteredDevServerOptions: TWebpackDevServer.Configuration[] = webpackConfiguration\n .map((configuration) => configuration.devServer)\n .filter((devServer): devServer is TWebpackDevServer.Configuration => !!devServer);\n if (filteredDevServerOptions.length > 1) {\n taskSession.logger.emitWarning(\n new Error(`Detected multiple webpack devServer configurations, using the first one.`)\n );\n }\n devServerOptions = { ...defaultDevServerOptions, ...filteredDevServerOptions[0] };\n } else {\n devServerOptions = { ...defaultDevServerOptions, ...webpackConfiguration.devServer };\n }\n\n // Add the certificate and key to the devServerOptions if these fields don't already have values\n if (!devServerOptions.server) {\n const certificateManager: CertificateManager = new CertificateManager();\n const certificate: ICertificate = await certificateManager.ensureCertificateAsync(\n true,\n taskSession.logger.terminal\n );\n\n // Update the web socket URL to use the hostname provided by the certificate\n const clientConfiguration: TWebpackDevServer.Configuration['client'] = devServerOptions.client;\n const hostname: string | undefined = certificate.subjectAltNames?.[0];\n if (hostname && typeof clientConfiguration === 'object') {\n const { webSocketURL } = clientConfiguration;\n if (typeof webSocketURL === 'object') {\n clientConfiguration.webSocketURL = {\n ...webSocketURL,\n hostname\n };\n }\n }\n\n devServerOptions = {\n ...devServerOptions,\n server: {\n type: 'https',\n options: {\n minVersion: 'TLSv1.3',\n key: certificate.pemKey,\n cert: certificate.pemCertificate,\n ca: certificate.pemCaCertificate\n }\n }\n };\n }\n\n // Since the webpack-dev-server does not return infrastructure errors via a callback like\n // compiler.watch(...), we will need to intercept them and log them ourselves.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n compiler.hooks.infrastructureLog.tap(PLUGIN_NAME, (name: string, type: string, args: any[]) => {\n if (name === WEBPACK_DEV_MIDDLEWARE_PACKAGE_NAME && type === 'error') {\n const error: Error | undefined = args[0];\n if (error) {\n taskSession.logger.emitError(error);\n }\n }\n return true;\n });\n\n // The webpack-dev-server package has a design flaw, where merely loading its package will set the\n // WEBPACK_DEV_SERVER environment variable -- even if no APIs are accessed. This environment variable\n // causes incorrect behavior if Heft is not running in serve mode. Thus, we need to be careful to call\n // require() only if Heft is in serve mode.\n taskSession.logger.terminal.writeLine('Starting webpack-dev-server');\n const WebpackDevServer: typeof TWebpackDevServer = (await import(WEBPACK_DEV_SERVER_PACKAGE_NAME))\n .default;\n const webpackDevServer: TWebpackDevServer = new WebpackDevServer(devServerOptions, compiler);\n await webpackDevServer.start();\n } else {\n // Create the watcher. Compilation will start immediately after invoking watch().\n taskSession.logger.terminal.writeLine('Starting Webpack watcher');\n compiler.watch({}, (error?: Error | null) => {\n if (error) {\n taskSession.logger.emitError(error);\n }\n });\n }\n }\n\n let hasChanges: boolean = true;\n if (!isInitial && this._watchFileSystems) {\n hasChanges = false;\n for (const watchFileSystem of this._watchFileSystems) {\n hasChanges = watchFileSystem.flush() || hasChanges;\n }\n }\n\n // Resume the compilation, wait for the compilation to complete, then suspend the watchers until the\n // next iteration. Even if there are no changes, the promise should resolve since resuming from a\n // suspended state invalidates the state of the watcher.\n if (hasChanges) {\n taskSession.logger.terminal.writeLine('Running incremental Webpack compilation');\n await webpackCompilationDonePromise;\n } else {\n taskSession.logger.terminal.writeLine(\n 'Webpack has not detected changes. Listing previous diagnostics.'\n );\n }\n\n this._emitErrors(taskSession.logger);\n }\n\n private _validateEnvironmentVariable(taskSession: IHeftTaskSession): void {\n if (!this._isServeMode && process.env[WEBPACK_DEV_SERVER_ENV_VAR_NAME]) {\n taskSession.logger.emitWarning(\n new Error(\n `The \"${WEBPACK_DEV_SERVER_ENV_VAR_NAME}\" environment variable is set, ` +\n 'which will cause problems when webpack is not running in serve mode. ' +\n `(Did a dependency inadvertently load the \"${WEBPACK_DEV_SERVER_PACKAGE_NAME}\" package?)`\n )\n );\n }\n }\n\n private _emitErrors(logger: IScopedLogger): void {\n for (const warning of this._warnings) {\n logger.emitWarning(warning);\n }\n for (const error of this._errors) {\n logger.emitError(error);\n }\n }\n\n private _recordErrors(stats: TWebpack.Stats | TWebpack.MultiStats, buildFolderPath: string): void {\n const errors: Error[] = this._errors;\n const warnings: Error[] = this._warnings;\n\n errors.length = 0;\n warnings.length = 0;\n\n if (stats.hasErrors() || stats.hasWarnings()) {\n const serializedStats: TWebpack.StatsCompilation[] = [stats.toJson('errors-warnings')];\n\n for (const compilationStats of serializedStats) {\n if (compilationStats.warnings) {\n for (const warning of compilationStats.warnings) {\n warnings.push(this._normalizeError(buildFolderPath, warning));\n }\n }\n\n if (compilationStats.errors) {\n for (const error of compilationStats.errors) {\n errors.push(this._normalizeError(buildFolderPath, error));\n }\n }\n\n if (compilationStats.children) {\n for (const child of compilationStats.children) {\n serializedStats.push(child);\n }\n }\n }\n }\n }\n\n private _normalizeError(buildFolderPath: string, error: TWebpack.StatsError): Error {\n if (error instanceof Error) {\n return error;\n } else if (error.moduleIdentifier) {\n let lineNumber: number | undefined;\n let columnNumber: number | undefined;\n if (error.loc) {\n // Format of \"<line>:<columnStart>-<columnEnd>\"\n // https://webpack.js.org/api/stats/#errors-and-warnings\n const [lineNumberRaw, columnRangeRaw] = error.loc.split(':');\n const [startColumnRaw] = columnRangeRaw.split('-');\n if (lineNumberRaw) {\n lineNumber = parseInt(lineNumberRaw, 10);\n if (isNaN(lineNumber)) {\n lineNumber = undefined;\n }\n }\n if (startColumnRaw) {\n columnNumber = parseInt(startColumnRaw, 10);\n if (isNaN(columnNumber)) {\n columnNumber = undefined;\n }\n }\n }\n\n return new FileError(error.message, {\n absolutePath: error.moduleIdentifier,\n projectFolder: buildFolderPath,\n line: lineNumber,\n column: columnNumber\n });\n } else {\n return new Error(error.message);\n }\n }\n}\n"]}
@@ -1,7 +1,19 @@
1
- import type { IBuildStageProperties, ScopedLogger } from '@rushstack/heft';
2
- import { IWebpackConfiguration } from './shared';
1
+ import type * as TWebpack from 'webpack';
2
+ import type { IScopedLogger, IHeftTaskSession, HeftConfiguration } from '@rushstack/heft';
3
+ import type { IWebpackPluginOptions } from './Webpack5Plugin';
4
+ import type { IWebpackConfiguration } from './shared';
5
+ interface ILoadWebpackConfigurationOptions extends IWebpackPluginOptions {
6
+ taskSession: IHeftTaskSession;
7
+ heftConfiguration: HeftConfiguration;
8
+ loadWebpackAsyncFn: () => Promise<typeof TWebpack>;
9
+ }
3
10
  export declare class WebpackConfigurationLoader {
4
- static tryLoadWebpackConfigAsync(logger: ScopedLogger, buildFolder: string, buildProperties: IBuildStageProperties): Promise<IWebpackConfiguration | undefined>;
5
- private static _tryLoadWebpackConfiguration;
11
+ private readonly _logger;
12
+ private readonly _production;
13
+ private readonly _serveMode;
14
+ constructor(logger: IScopedLogger, production: boolean, serveMode: boolean);
15
+ tryLoadWebpackConfigurationAsync(options: ILoadWebpackConfigurationOptions): Promise<IWebpackConfiguration | undefined>;
16
+ private _tryLoadWebpackConfigurationInnerAsync;
6
17
  }
18
+ export {};
7
19
  //# sourceMappingURL=WebpackConfigurationLoader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WebpackConfigurationLoader.d.ts","sourceRoot":"","sources":["../src/WebpackConfigurationLoader.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAuBjD,qBAAa,0BAA0B;WACjB,yBAAyB,CAC3C,MAAM,EAAE,YAAY,EACpB,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,qBAAqB,GACrC,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC;IAgD7C,OAAO,CAAC,MAAM,CAAC,4BAA4B;CAe5C"}
1
+ {"version":3,"file":"WebpackConfigurationLoader.d.ts","sourceRoot":"","sources":["../src/WebpackConfigurationLoader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,QAAQ,MAAM,SAAS,CAAC;AAEzC,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAE1F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,KAAK,EAAE,qBAAqB,EAAsC,MAAM,UAAU,CAAC;AAW1F,UAAU,gCAAiC,SAAQ,qBAAqB;IACtE,WAAW,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,kBAAkB,EAAE,MAAM,OAAO,CAAC,OAAO,QAAQ,CAAC,CAAC;CACpD;AAKD,qBAAa,0BAA0B;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAU;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;gBAElB,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO;IAMpE,gCAAgC,CAC3C,OAAO,EAAE,gCAAgC,GACxC,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC;YAwD/B,sCAAsC;CAmBrD"}
@@ -28,31 +28,46 @@ Object.defineProperty(exports, "__esModule", { value: true });
28
28
  exports.WebpackConfigurationLoader = void 0;
29
29
  const path = __importStar(require("path"));
30
30
  const node_core_library_1 = require("@rushstack/node-core-library");
31
+ const DEFAULT_WEBPACK_CONFIG_PATH = './webpack.config.js';
32
+ const DEFAULT_WEBPACK_DEV_CONFIG_PATH = './webpack.dev.config.js';
31
33
  class WebpackConfigurationLoader {
32
- static async tryLoadWebpackConfigAsync(logger, buildFolder, buildProperties) {
34
+ constructor(logger, production, serveMode) {
35
+ this._logger = logger;
36
+ this._production = production;
37
+ this._serveMode = serveMode;
38
+ }
39
+ async tryLoadWebpackConfigurationAsync(options) {
33
40
  // TODO: Eventually replace this custom logic with a call to this utility in in webpack-cli:
34
41
  // https://github.com/webpack/webpack-cli/blob/next/packages/webpack-cli/lib/groups/ConfigGroup.js
35
- const webpackConfigFiles = await findWebpackConfigAsync(buildFolder);
36
- const webpackDevConfigFilename = webpackConfigFiles.dev;
37
- const webpackConfigFilename = webpackConfigFiles.prod;
42
+ const { taskSession, heftConfiguration, configurationPath, devConfigurationPath, loadWebpackAsyncFn } = options;
38
43
  let webpackConfigJs;
39
44
  try {
40
- if (buildProperties.serveMode && webpackDevConfigFilename) {
41
- logger.terminal.writeVerboseLine(`Attempting to load webpack configuration from "${webpackDevConfigFilename}".`);
42
- webpackConfigJs = WebpackConfigurationLoader._tryLoadWebpackConfiguration(buildFolder, webpackDevConfigFilename);
45
+ const buildFolderPath = heftConfiguration.buildFolderPath;
46
+ if (this._serveMode) {
47
+ const devConfigPath = path.resolve(buildFolderPath, devConfigurationPath || DEFAULT_WEBPACK_DEV_CONFIG_PATH);
48
+ this._logger.terminal.writeVerboseLine(`Attempting to load webpack configuration from "${devConfigPath}".`);
49
+ webpackConfigJs = await this._tryLoadWebpackConfigurationInnerAsync(devConfigPath);
43
50
  }
44
- if (!webpackConfigJs && webpackConfigFilename) {
45
- logger.terminal.writeVerboseLine(`Attempting to load webpack configuration from "${webpackConfigFilename}".`);
46
- webpackConfigJs = WebpackConfigurationLoader._tryLoadWebpackConfiguration(buildFolder, webpackConfigFilename);
51
+ if (!webpackConfigJs) {
52
+ const configPath = path.resolve(buildFolderPath, configurationPath || DEFAULT_WEBPACK_CONFIG_PATH);
53
+ this._logger.terminal.writeVerboseLine(`Attempting to load webpack configuration from "${configPath}".`);
54
+ webpackConfigJs = await this._tryLoadWebpackConfigurationInnerAsync(configPath);
47
55
  }
48
56
  }
49
57
  catch (error) {
50
- logger.emitError(error);
58
+ this._logger.emitError(error);
51
59
  }
52
60
  if (webpackConfigJs) {
53
61
  const webpackConfig = webpackConfigJs.default || webpackConfigJs;
54
62
  if (typeof webpackConfig === 'function') {
55
- return webpackConfig({ prod: buildProperties.production, production: buildProperties.production });
63
+ // Defer loading of webpack until we know for sure that we will need it
64
+ return webpackConfig({
65
+ prod: this._production,
66
+ production: this._production,
67
+ taskSession,
68
+ heftConfiguration,
69
+ webpack: await loadWebpackAsyncFn()
70
+ });
56
71
  }
57
72
  else {
58
73
  return webpackConfig;
@@ -62,14 +77,19 @@ class WebpackConfigurationLoader {
62
77
  return undefined;
63
78
  }
64
79
  }
65
- static _tryLoadWebpackConfiguration(buildFolder, configurationFilename) {
66
- const fullWebpackConfigPath = path.join(buildFolder, configurationFilename);
67
- if (node_core_library_1.FileSystem.exists(fullWebpackConfigPath)) {
80
+ async _tryLoadWebpackConfigurationInnerAsync(configurationPath) {
81
+ const configExists = await node_core_library_1.FileSystem.existsAsync(configurationPath);
82
+ if (configExists) {
68
83
  try {
69
- return require(fullWebpackConfigPath);
84
+ return await Promise.resolve().then(() => __importStar(require(configurationPath)));
70
85
  }
71
86
  catch (e) {
72
- throw new Error(`Error loading webpack configuration at "${fullWebpackConfigPath}": ${e}`);
87
+ const error = e;
88
+ if (error.code === 'ERR_MODULE_NOT_FOUND') {
89
+ // No configuration found, return undefined.
90
+ return undefined;
91
+ }
92
+ throw new Error(`Error loading webpack configuration at "${configurationPath}": ${e}`);
73
93
  }
74
94
  }
75
95
  else {
@@ -78,34 +98,4 @@ class WebpackConfigurationLoader {
78
98
  }
79
99
  }
80
100
  exports.WebpackConfigurationLoader = WebpackConfigurationLoader;
81
- async function findWebpackConfigAsync(buildFolder) {
82
- try {
83
- const folderItems = await node_core_library_1.FileSystem.readFolderItemsAsync(buildFolder);
84
- const dev = [];
85
- const prod = [];
86
- for (const folderItem of folderItems) {
87
- if (folderItem.isFile()) {
88
- if (folderItem.name.match(/^webpack.dev.config\.(cjs|js|mjs)$/)) {
89
- dev.push(folderItem.name);
90
- }
91
- else if (folderItem.name.match(/^webpack.config\.(cjs|js|mjs)$/)) {
92
- prod.push(folderItem.name);
93
- }
94
- }
95
- }
96
- if (dev.length > 1) {
97
- throw new Error(`Error: Found more than one dev webpack configuration file.`);
98
- }
99
- else if (prod.length > 1) {
100
- throw new Error(`Error: Found more than one non-dev webpack configuration file.`);
101
- }
102
- return {
103
- dev: dev[0],
104
- prod: prod[0]
105
- };
106
- }
107
- catch (e) {
108
- throw new Error(`Error finding webpack configuration: ${e}`);
109
- }
110
- }
111
101
  //# sourceMappingURL=WebpackConfigurationLoader.js.map