"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.restoreLoadHook = exports.getMajorVersion = exports.sourceDefaultWebpackDependencies = exports.sourceHtmlWebpackPlugin = exports.sourceWebpackDevServer = exports.sourceWebpack = exports.sourceFramework = exports.cypressWebpackPath = void 0; const tslib_1 = require("tslib"); const module_1 = tslib_1.__importDefault(require("module")); const path_1 = tslib_1.__importDefault(require("path")); const debug_1 = tslib_1.__importDefault(require("debug")); const debug = (0, debug_1.default)('cypress:webpack-dev-server:sourceRelativeWebpackModules'); const originalModuleLoad = module_1.default._load; const originalModuleResolveFilename = module_1.default._resolveFilename; // We ship webpack@4 as part of '@cypress/webpack-batteries-included-preprocessor'. The path to this module // serves as our fallback. const cypressWebpackPath = (config) => { return require.resolve('@cypress/webpack-batteries-included-preprocessor', { paths: [config.cypressConfig.cypressBinaryRoot], }); }; exports.cypressWebpackPath = cypressWebpackPath; const frameworkWebpackMapper = { 'create-react-app': 'react-scripts', 'vue-cli': '@vue/cli-service', 'nuxt': '@nuxt/webpack', react: undefined, vue: undefined, next: 'next', 'angular': '@angular-devkit/build-angular', 'svelte': undefined, }; // Source the users framework from the provided projectRoot. The framework, if available, will serve // as the resolve base for webpack dependency resolution. function sourceFramework(config) { debug('Framework: Attempting to source framework for %s', config.cypressConfig.projectRoot); if (!config.framework) { debug('Framework: No framework provided'); return null; } const sourceOfWebpack = frameworkWebpackMapper[config.framework]; if (!sourceOfWebpack) { debug('Not a higher-order framework so webpack dependencies should be resolvable from projectRoot'); return null; } const framework = {}; try { const frameworkJsonPath = require.resolve(`${sourceOfWebpack}/package.json`, { paths: [config.cypressConfig.projectRoot], }); const frameworkPathRoot = path_1.default.dirname(frameworkJsonPath); // Want to make sure we're sourcing this from the user's code. Otherwise we can // warn and tell them they don't have their dependencies installed framework.importPath = frameworkPathRoot; framework.packageJson = require(frameworkJsonPath); debug('Framework: Successfully sourced framework - %o', framework); return framework; } catch (e) { debug('Framework: Failed to source framework - %s', e); // TODO return null; } } exports.sourceFramework = sourceFramework; // Source the webpack module from the provided framework or projectRoot. We override the module resolution // so that other packages that import webpack resolve to the version we found. // If none is found, we fallback to the bundled version in '@cypress/webpack-batteries-included-preprocessor'. function sourceWebpack(config, framework) { var _a; const searchRoot = (_a = framework === null || framework === void 0 ? void 0 : framework.importPath) !== null && _a !== void 0 ? _a : config.cypressConfig.projectRoot; debug('Webpack: Attempting to source webpack from %s', searchRoot); const webpack = {}; let webpackJsonPath; try { webpackJsonPath = require.resolve('webpack/package.json', { paths: [searchRoot], }); } catch (e) { if (e.code !== 'MODULE_NOT_FOUND') { debug('Webpack: Failed to source webpack - %s', e); throw e; } debug('Webpack: Falling back to bundled version'); webpackJsonPath = require.resolve('webpack/package.json', { paths: [(0, exports.cypressWebpackPath)(config)], }); } webpack.importPath = path_1.default.dirname(webpackJsonPath); webpack.packageJson = require(webpackJsonPath); webpack.module = require(webpack.importPath); webpack.majorVersion = getMajorVersion(webpack.packageJson, [4, 5]); debug('Webpack: Successfully sourced webpack - %o', webpack); module_1.default._load = function (request, parent, isMain) { if (request === 'webpack' || request.startsWith('webpack/')) { const resolvePath = require.resolve(request, { paths: [webpack.importPath], }); debug('Webpack: Module._load resolvePath - %s', resolvePath); return originalModuleLoad(resolvePath, parent, isMain); } return originalModuleLoad(request, parent, isMain); }; module_1.default._resolveFilename = function (request, parent, isMain, options) { if (request === 'webpack' || request.startsWith('webpack/') && !(options === null || options === void 0 ? void 0 : options.paths)) { const resolveFilename = originalModuleResolveFilename(request, parent, isMain, { paths: [webpack.importPath], }); debug('Webpack: Module._resolveFilename resolveFilename - %s', resolveFilename); return resolveFilename; } return originalModuleResolveFilename(request, parent, isMain, options); }; return webpack; } exports.sourceWebpack = sourceWebpack; // Source the webpack-dev-server module from the provided framework or projectRoot. // If none is found, we fallback to the version bundled with this package. function sourceWebpackDevServer(config, framework) { var _a; const searchRoot = (_a = framework === null || framework === void 0 ? void 0 : framework.importPath) !== null && _a !== void 0 ? _a : config.cypressConfig.projectRoot; debug('WebpackDevServer: Attempting to source webpack-dev-server from %s', searchRoot); const webpackDevServer = {}; let webpackDevServerJsonPath; try { webpackDevServerJsonPath = require.resolve('webpack-dev-server/package.json', { paths: [searchRoot], }); } catch (e) { if (e.code !== 'MODULE_NOT_FOUND') { debug('WebpackDevServer: Failed to source webpack-dev-server - %s', e); throw e; } debug('WebpackDevServer: Falling back to bundled version'); webpackDevServerJsonPath = require.resolve('webpack-dev-server/package.json', { paths: [__dirname], }); } webpackDevServer.importPath = path_1.default.dirname(webpackDevServerJsonPath); webpackDevServer.packageJson = require(webpackDevServerJsonPath); webpackDevServer.module = require(webpackDevServer.importPath); webpackDevServer.majorVersion = getMajorVersion(webpackDevServer.packageJson, [3, 4]); debug('WebpackDevServer: Successfully sourced webpack-dev-server - %o', webpackDevServer); return webpackDevServer; } exports.sourceWebpackDevServer = sourceWebpackDevServer; // Source the html-webpack-plugin module from the provided framework or projectRoot. // If none is found, we fallback to the version bundled with this package dependent on the major version of webpack. // We ship both v4 and v5 of 'html-webpack-plugin' by aliasing the package with the major version (check package.json). function sourceHtmlWebpackPlugin(config, framework, webpack) { var _a; const searchRoot = (_a = framework === null || framework === void 0 ? void 0 : framework.importPath) !== null && _a !== void 0 ? _a : config.cypressConfig.projectRoot; debug('HtmlWebpackPlugin: Attempting to source html-webpack-plugin from %s', searchRoot); const htmlWebpackPlugin = {}; let htmlWebpackPluginJsonPath; try { htmlWebpackPluginJsonPath = require.resolve('html-webpack-plugin/package.json', { paths: [searchRoot], }); htmlWebpackPlugin.packageJson = require(htmlWebpackPluginJsonPath); // Check that they're not using v3 of html-webpack-plugin. Since we should be the only consumer of it, // we shouldn't be concerned with using our own copy if they've shipped w/ an earlier version htmlWebpackPlugin.majorVersion = getMajorVersion(htmlWebpackPlugin.packageJson, [4, 5]); } catch (e) { const err = e; if (err.code !== 'MODULE_NOT_FOUND' && !err.message.includes('Unexpected major version')) { debug('HtmlWebpackPlugin: Failed to source html-webpack-plugin - %s', e); throw e; } const htmlWebpack = `html-webpack-plugin-${webpack.majorVersion}`; debug('HtmlWebpackPlugin: Falling back to bundled version %s', htmlWebpack); htmlWebpackPluginJsonPath = require.resolve(`${htmlWebpack}/package.json`, { paths: [ __dirname, ], }); } htmlWebpackPlugin.importPath = path_1.default.dirname(htmlWebpackPluginJsonPath), htmlWebpackPlugin.packageJson = require(htmlWebpackPluginJsonPath), htmlWebpackPlugin.module = require(htmlWebpackPlugin.importPath), htmlWebpackPlugin.majorVersion = getMajorVersion(htmlWebpackPlugin.packageJson, [4, 5]); debug('HtmlWebpackPlugin: Successfully sourced html-webpack-plugin - %o', htmlWebpackPlugin); return htmlWebpackPlugin; } exports.sourceHtmlWebpackPlugin = sourceHtmlWebpackPlugin; // Most frameworks follow a similar path for sourcing webpack dependencies so this is a utility to handle all the sourcing. function sourceDefaultWebpackDependencies(config) { const framework = sourceFramework(config); const webpack = sourceWebpack(config, framework); const webpackDevServer = sourceWebpackDevServer(config, framework); const htmlWebpackPlugin = sourceHtmlWebpackPlugin(config, framework, webpack); return { framework, webpack, webpackDevServer, htmlWebpackPlugin, }; } exports.sourceDefaultWebpackDependencies = sourceDefaultWebpackDependencies; function getMajorVersion(json, acceptedVersions) { const major = Number(json.version.split('.')[0]); if (!acceptedVersions.includes(major)) { throw new Error(`Unexpected major version of ${json.name}. ` + `Cypress webpack-dev-server works with ${json.name} versions ${acceptedVersions.join(', ')} - saw ${json.version}`); } return Number(major); } exports.getMajorVersion = getMajorVersion; function restoreLoadHook() { module_1.default._load = originalModuleLoad; module_1.default._resolveFilename = originalModuleResolveFilename; } exports.restoreLoadHook = restoreLoadHook;