'use strict'; var ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); var cliCommon = require('@backstage/cli-common'); var getPackages = require('@manypkg/get-packages'); var ESLintPlugin = require('eslint-webpack-plugin'); var ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); var fs = require('fs-extra'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var pickBy = require('lodash/pickBy'); var webpack = require('webpack'); var yn = require('yn'); var path = require('path'); var index = require('./index-79e50cf7.cjs.js'); var errors = require('@backstage/errors'); var child_process = require('child_process'); var util = require('util'); var dynamicPluginSdkWebpack = require('@openshift/dynamic-plugin-sdk-webpack'); var ReactRefreshPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); var MiniCssExtractPlugin = require('mini-css-extract-plugin'); var cliNode = require('@backstage/cli-node'); var config = require('@backstage/config'); var configLoader = require('@backstage/config-loader'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var ModuleScopePlugin__default = /*#__PURE__*/_interopDefaultLegacy(ModuleScopePlugin); var ESLintPlugin__default = /*#__PURE__*/_interopDefaultLegacy(ESLintPlugin); var ForkTsCheckerWebpackPlugin__default = /*#__PURE__*/_interopDefaultLegacy(ForkTsCheckerWebpackPlugin); var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs); var HtmlWebpackPlugin__default = /*#__PURE__*/_interopDefaultLegacy(HtmlWebpackPlugin); var pickBy__default = /*#__PURE__*/_interopDefaultLegacy(pickBy); var webpack__default = /*#__PURE__*/_interopDefaultLegacy(webpack); var yn__default = /*#__PURE__*/_interopDefaultLegacy(yn); var ReactRefreshPlugin__default = /*#__PURE__*/_interopDefaultLegacy(ReactRefreshPlugin); var MiniCssExtractPlugin__default = /*#__PURE__*/_interopDefaultLegacy(MiniCssExtractPlugin); const execFile = util.promisify(child_process.execFile); async function run(name, args = [], options = {}) { var _a; const { stdoutLogFunc, stderrLogFunc } = options; const env = { ...process.env, FORCE_COLOR: "true", ...(_a = options.env) != null ? _a : {} }; const stdio = [ "inherit", stdoutLogFunc ? "pipe" : "inherit", stderrLogFunc ? "pipe" : "inherit" ]; const child = child_process.spawn(name, args, { stdio, shell: true, ...options, env }); if (stdoutLogFunc && child.stdout) { child.stdout.on("data", stdoutLogFunc); } if (stderrLogFunc && child.stderr) { child.stderr.on("data", stderrLogFunc); } await waitForExit(child, name); } async function runPlain(cmd, ...args) { try { const { stdout } = await execFile(cmd, args, { shell: true }); return stdout.trim(); } catch (error) { errors.assertError(error); if ("stderr" in error) { process.stderr.write(error.stderr); } if (typeof error.code === "number") { throw new index.ExitCodeError(error.code, [cmd, ...args].join(" ")); } throw new errors.ForwardedError("Unknown execution error", error); } } async function waitForExit(child, name) { if (typeof child.exitCode === "number") { if (child.exitCode) { throw new index.ExitCodeError(child.exitCode, name); } return; } await new Promise((resolve, reject) => { child.once("error", (error) => reject(error)); child.once("exit", (code) => { if (code) { reject(new index.ExitCodeError(code, name)); } else { resolve(); } }); }); } class LinkedPackageResolvePlugin { constructor(targetModules, packages) { this.targetModules = targetModules; this.packages = packages; } apply(resolver) { resolver.hooks.resolve.tapAsync( "LinkedPackageResolvePlugin", (data, context, callback) => { var _a; const pkg = this.packages.find( (pkge) => data.path && cliCommon.isChildPath(pkge.dir, data.path) ); if (!pkg) { callback(); return; } const modulesLocation = path.resolve( this.targetModules, pkg.packageJson.name ); const newContext = ((_a = data.context) == null ? void 0 : _a.issuer) ? { ...data.context, issuer: data.context.issuer.replace(pkg.dir, modulesLocation) } : data.context; resolver.doResolve( resolver.hooks.resolve, { ...data, context: newContext, path: data.path && data.path.replace(pkg.dir, modulesLocation) }, `resolve ${data.request} in ${modulesLocation}`, context, callback ); } ); } } const { ESBuildMinifyPlugin } = require("esbuild-loader"); const optimization = (options) => { const { isDev } = options; return { minimize: !isDev, minimizer: [ new ESBuildMinifyPlugin({ target: "es2019", format: "iife" }) ], runtimeChunk: "single", splitChunks: { automaticNameDelimiter: "-", cacheGroups: { default: false, // Put all vendor code needed for initial page load in individual files if they're big // enough, if they're smaller they end up in the main packages: { chunks: "initial", test(module) { var _a; return Boolean( (_a = module == null ? void 0 : module.resource) == null ? void 0 : _a.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/) ); }, name(module) { const packageName = module.resource.match( /[\\/]node_modules[\\/](.*?)([\\/]|$)/ )[1]; return packageName.replace("@", ""); }, filename: isDev ? "module-[name].js" : "static/module-[name].[chunkhash:8].js", priority: 10, minSize: 1e5, minChunks: 1, maxAsyncRequests: Infinity, maxInitialRequests: Infinity }, // filename is not included in type, but we need it // Group together the smallest modules vendor: { chunks: "initial", test: /[\\/]node_modules[\\/]/, name: "vendor", priority: 5, enforce: true } } } }; }; function svgrTemplate({ imports, interfaces, componentName, props, jsx }, { tpl }) { const name = `${componentName.replace(/icon$/, "")}Icon`; const defaultExport = { type: "ExportDefaultDeclaration", declaration: { type: "Identifier", name } }; return tpl` ${imports} import SvgIcon from '@material-ui/core/SvgIcon'; ${interfaces} const ${name} = (${props}) => React.createElement(SvgIcon, ${props}, ${jsx.children}); ${defaultExport}`; } const transforms = (options) => { const { isDev, isBackend } = options; function insertBeforeJssStyles(element) { const head = document.head; const firstJssNode = head.querySelector("style[data-jss]"); if (!firstJssNode) { head.appendChild(element); } else { head.insertBefore(element, firstJssNode); } } const loaders = [ { test: /\.(tsx?)$/, exclude: /node_modules/, use: [ { loader: require.resolve("swc-loader"), options: { jsc: { target: "es2019", externalHelpers: !isBackend, parser: { syntax: "typescript", tsx: !isBackend, dynamicImport: true }, transform: { react: isBackend ? void 0 : { runtime: "automatic", refresh: isDev } } } } } ] }, { test: /\.(jsx?|mjs|cjs)$/, exclude: /node_modules/, use: [ { loader: require.resolve("swc-loader"), options: { jsc: { target: "es2019", externalHelpers: !isBackend, parser: { syntax: "ecmascript", jsx: !isBackend, dynamicImport: true }, transform: { react: isBackend ? void 0 : { runtime: "automatic", refresh: isDev } } } } } ] }, { test: /\.(js|mjs|cjs)$/, resolve: { fullySpecified: false } }, { test: [/\.icon\.svg$/], use: [ { loader: require.resolve("swc-loader"), options: { jsc: { target: "es2019", externalHelpers: !isBackend, parser: { syntax: "ecmascript", jsx: !isBackend, dynamicImport: true } } } }, { loader: require.resolve("@svgr/webpack"), options: { babel: false, template: svgrTemplate } } ] }, { test: [ /\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/, /\.frag$/, /\.vert$/, { and: [/\.svg$/, { not: [/\.icon\.svg$/] }] }, /\.xml$/ ], type: "asset/resource", generator: { filename: "static/[name].[hash:8].[ext]" } }, { test: /\.(eot|woff|woff2|ttf)$/i, type: "asset/resource", generator: { filename: "static/[name].[hash][ext][query]" } }, { test: /\.ya?ml$/, use: require.resolve("yml-loader") }, { include: /\.(md)$/, type: "asset/resource", generator: { filename: "static/[name].[hash][ext][query]" } }, { test: /\.css$/i, use: [ isDev ? { loader: require.resolve("style-loader"), options: { insert: insertBeforeJssStyles } } : MiniCssExtractPlugin__default["default"].loader, { loader: require.resolve("css-loader"), options: { sourceMap: true } } ] } ]; const plugins = new Array(); if (isDev) { if (!isBackend) { plugins.push( new ReactRefreshPlugin__default["default"]({ overlay: { sockProtocol: "ws" } }) ); } } else { plugins.push( new MiniCssExtractPlugin__default["default"]({ filename: "static/[name].[contenthash:8].css", chunkFilename: "static/[name].[id].[contenthash:8].css", insert: insertBeforeJssStyles // Only applies to async chunks }) ); } return { loaders, plugins }; }; const sharedModules = { /** * Mandatory singleton packages for sharing */ react: { singleton: true, requiredVersion: "*" }, "react-dom": { singleton: true, requiredVersion: "*" }, "react-router-dom": { singleton: true, requiredVersion: "*" }, "react-router": { singleton: true, requiredVersion: "*" }, "@backstage/version-bridge": { singleton: true, requiredVersion: "*" }, "@backstage/core-app-api": { singleton: true, requiredVersion: "*" }, "@backstage/core-plugin-api": { singleton: true, requiredVersion: "*" }, "@backstage/frontend-plugin-api": { singleton: true, requiredVersion: "*" }, "@scalprum/react-core": { singleton: true, requiredVersion: "*" }, "@openshift/dynamic-plugin-sdk": { singleton: true, requiredVersion: "*" }, /** * The following two packages are required to be shared as singletons to enable UI theming */ "@material-ui/core/styles": { singleton: true, requiredVersion: "*" }, "@material-ui/styles": { singleton: true, requiredVersion: "*" } }; async function createScalprumConfig(paths, options) { const { checksEnabled, isDev } = options; const { plugins, loaders } = transforms({ ...options, isDev: !!options.isDev }); if (checksEnabled) { plugins.push( new ForkTsCheckerWebpackPlugin__default["default"]({ typescript: { configFile: paths.targetTsConfig, memoryLimit: 4096 } }), new ESLintPlugin__default["default"]({ context: paths.targetPath, files: ["**/*.(ts|tsx|mts|cts|js|jsx|mjs|cjs)"] }) ); } plugins.push( new webpack.ProvidePlugin({ process: "process/browser", Buffer: ["buffer", "Buffer"] }) ); plugins.push( new webpack__default["default"].EnvironmentPlugin({ HAS_REACT_DOM_CLIENT: false, APP_CONFIG: options.frontendAppConfigs }) ); const dynamicPluginPlugin = new dynamicPluginSdkWebpack.DynamicRemotePlugin({ extensions: [], sharedModules, entryScriptFilename: `${options.pluginMetadata.name}.[fullhash].js`, pluginMetadata: { ...options.pluginMetadata } }); plugins.push(dynamicPluginPlugin); return { mode: isDev ? "development" : "production", profile: false, bail: false, performance: { hints: false // we check the gzip size instead }, devtool: isDev ? "eval-cheap-module-source-map" : "source-map", context: paths.targetPath, entry: {}, // Plugin container entry is generated by DynamicRemotePlugin resolve: { alias: { "@backstage/frontend-app-api/src": path.join( process.cwd(), "src", "overrides", "@backstage", "frontend-app-api", "src" ) }, extensions: [".ts", ".tsx", ".mjs", ".js", ".jsx", ".json", ".wasm"] }, module: { rules: loaders }, output: { path: paths.targetScalprumDist, publicPath: "auto", filename: isDev ? "[name].js" : "static/[name].[fullhash:8].js", chunkFilename: isDev ? "[name].chunk.js" : "static/[name].[chunkhash:8].chunk.js", ...isDev ? { devtoolModuleFilenameTemplate: (info) => `file:///${path.resolve(info.absoluteResourcePath).replace( /\\/g, "/" )}` } : {} }, plugins }; } const { ModuleFederationPlugin } = webpack.container; const scalprumPlugin = new ModuleFederationPlugin({ name: "backstageHost", filename: "backstageHost.[fullhash].js", shared: [sharedModules] }); const BUILD_CACHE_ENV_VAR = "BACKSTAGE_CLI_EXPERIMENTAL_BUILD_CACHE"; function resolveBaseUrl(config) { const baseUrl = config.getString("app.baseUrl"); try { return new URL(baseUrl); } catch (error) { throw new Error(`Invalid app.baseUrl, ${error}`); } } async function readBuildInfo() { const timestamp = Date.now(); let commit = "unknown"; try { commit = await runPlain("git", "rev-parse", "HEAD"); } catch (error) { console.warn(`WARNING: Failed to read git commit, ${error}`); } let gitVersion = "unknown"; try { gitVersion = await runPlain("git", "describe", "--always"); } catch (error) { console.warn(`WARNING: Failed to describe git version, ${error}`); } const { version: packageVersion } = await fs__default["default"].readJson( index.paths.resolveTarget("package.json") ); return { cliVersion: index.version, gitVersion, packageVersion, timestamp, commit }; } async function createConfig(paths, options) { var _a; const { checksEnabled, isDev, frontendConfig } = options; const { plugins, loaders } = transforms(options); const { packages } = await getPackages.getPackages(index.paths.targetDir); const externalPkgs = packages.filter((p) => !cliCommon.isChildPath(paths.root, p.dir)); const baseUrl = frontendConfig.getString("app.baseUrl"); const validBaseUrl = new URL(baseUrl); const publicPath = validBaseUrl.pathname.replace(/\/$/, ""); if (checksEnabled) { plugins.push( new ForkTsCheckerWebpackPlugin__default["default"]({ typescript: { configFile: paths.targetTsConfig, memoryLimit: 4096 } }), new ESLintPlugin__default["default"]({ context: paths.targetPath, files: ["**/*.(ts|tsx|mts|cts|js|jsx|mjs|cjs)"] }) ); } plugins.push( new webpack.ProvidePlugin({ process: "process/browser", Buffer: ["buffer", "Buffer"] }) ); plugins.push( new HtmlWebpackPlugin__default["default"]({ template: paths.targetHtml, templateParameters: { publicPath, config: frontendConfig } }) ); const buildInfo = await readBuildInfo(); plugins.push( new webpack__default["default"].DefinePlugin({ "process.env.HAS_REACT_DOM_CLIENT": false, "process.env.BUILD_INFO": JSON.stringify(buildInfo), "process.env.APP_CONFIG": webpack__default["default"].DefinePlugin.runtimeValue( () => JSON.stringify(options.getFrontendAppConfigs()), true ) }) ); plugins.push(scalprumPlugin); const reactRefreshFiles = [ require.resolve( "@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js" ), require.resolve("@pmmmwh/react-refresh-webpack-plugin/overlay/index.js"), require.resolve("react-refresh") ]; const withCache = yn__default["default"](process.env[BUILD_CACHE_ENV_VAR], { default: false }); return { cache: { type: "filesystem", allowCollectingMemory: true, cacheDirectory: path.join(process.cwd(), ".webpack-cache") }, mode: isDev ? "development" : "production", profile: false, optimization: optimization(options), bail: false, performance: { hints: false // we check the gzip size instead }, devtool: isDev ? "eval-cheap-module-source-map" : "source-map", context: paths.targetPath, entry: [...(_a = options.additionalEntryPoints) != null ? _a : [], paths.targetEntry], resolve: { alias: { "@backstage/frontend-app-api/src": path.join( process.cwd(), "src", "overrides", "@backstage", "frontend-app-api", "src" ) }, extensions: [".ts", ".tsx", ".mjs", ".js", ".jsx", ".json", ".wasm"], mainFields: ["browser", "module", "main"], fallback: { ...pickBy__default["default"](require("node-libs-browser")), module: false, dgram: false, dns: false, fs: false, http2: false, net: false, tls: false, child_process: false, /* new ignores */ path: false, https: false, http: false, util: require.resolve("util/") }, plugins: [ new LinkedPackageResolvePlugin(paths.rootNodeModules, externalPkgs), new ModuleScopePlugin__default["default"]( [paths.targetSrc, paths.targetDev], [paths.targetPackageJson, ...reactRefreshFiles] ) ] }, module: { rules: loaders }, output: { path: paths.targetDist, publicPath: `${publicPath}/`, filename: isDev ? "[name].js" : "static/[name].[fullhash:8].js", chunkFilename: isDev ? "[name].chunk.js" : "static/[name].[chunkhash:8].chunk.js", ...isDev ? { devtoolModuleFilenameTemplate: (info) => `file:///${path.resolve(info.absoluteResourcePath).replace( /\\/g, "/" )}` } : {} }, plugins, ...withCache ? { cache: { type: "filesystem", buildDependencies: { config: [__filename] } } } : {} }; } function resolveBundlingPaths(options) { const { entry, targetDir = index.paths.targetDir } = options; const resolveTargetModule = (pathString) => { for (const ext of ["mjs", "js", "ts", "tsx", "jsx"]) { const filePath = path.resolve(targetDir, `${pathString}.${ext}`); if (fs__default["default"].pathExistsSync(filePath)) { return filePath; } } return path.resolve(targetDir, `${pathString}.js`); }; let targetPublic = void 0; let targetHtml = path.resolve(targetDir, "public/index.html"); if (fs__default["default"].pathExistsSync(targetHtml)) { targetPublic = path.resolve(targetDir, "public"); } else { targetHtml = path.resolve(targetDir, `${entry}.html`); if (!fs__default["default"].pathExistsSync(targetHtml)) { targetHtml = index.paths.resolveOwn("templates/serve_index.html"); } } const targetRunFile = path.resolve(targetDir, "src/run.ts"); const runFileExists = fs__default["default"].pathExistsSync(targetRunFile); return { targetHtml, targetPublic, targetPath: path.resolve(targetDir, "."), targetRunFile: runFileExists ? targetRunFile : void 0, targetDist: path.resolve(targetDir, "dist"), targetScalprumDist: path.resolve(targetDir, "dist-scalprum"), targetAssets: path.resolve(targetDir, "assets"), targetSrc: path.resolve(targetDir, "src"), targetDev: path.resolve(targetDir, "dev"), targetEntry: resolveTargetModule(entry), targetTsConfig: index.paths.resolveTargetRoot("tsconfig.json"), targetPackageJson: path.resolve(targetDir, "package.json"), rootNodeModules: index.paths.resolveTargetRoot("node_modules"), root: index.paths.targetRoot }; } function isValidUrl(url) { try { new URL(url); return true; } catch { return false; } } async function loadCliConfig(options) { const configTargets = []; options.args.forEach((arg) => { if (!isValidUrl(arg)) { configTargets.push({ path: index.paths.resolveTarget(arg) }); } }); const { packages } = await getPackages.getPackages(index.paths.targetDir); let localPackageNames; if (options.fromPackage) { if (packages.length) { const graph = cliNode.PackageGraph.fromPackages(packages); localPackageNames = Array.from( graph.collectPackageNames([options.fromPackage], (node) => { if (node.name === "@janus-idp/cli") { return void 0; } return node.localDependencies.keys(); }) ); } else { localPackageNames = [options.fromPackage]; } } else { localPackageNames = packages.map((p) => p.packageJson.name); } const schema = await configLoader.loadConfigSchema({ dependencies: localPackageNames, // Include the package.json in the project root if it exists packagePaths: [index.paths.resolveTargetRoot("package.json")], noUndeclaredProperties: options.strict }); const { appConfigs } = await configLoader.loadConfig({ experimentalEnvFunc: options.mockEnv ? async (name) => process.env[name] || "x" : void 0, configRoot: index.paths.targetRoot, configTargets, watch: options.watch && { onChange(newAppConfigs) { var _a; const newFrontendAppConfigs = schema.process(newAppConfigs, { visibility: options.fullVisibility ? ["frontend", "backend", "secret"] : ["frontend"], withFilteredKeys: options.withFilteredKeys, withDeprecatedKeys: options.withDeprecatedKeys, ignoreSchemaErrors: !options.strict }); (_a = options.watch) == null ? void 0 : _a.call(options, newFrontendAppConfigs); } } }); process.stderr.write( `Loaded config from ${appConfigs.map((c) => c.context).join(", ")} ` ); try { const frontendAppConfigs = schema.process(appConfigs, { visibility: options.fullVisibility ? ["frontend", "backend", "secret"] : ["frontend"], withFilteredKeys: options.withFilteredKeys, withDeprecatedKeys: options.withDeprecatedKeys, ignoreSchemaErrors: !options.strict }); const frontendConfig = config.ConfigReader.fromConfigs(frontendAppConfigs); const fullConfig = config.ConfigReader.fromConfigs(appConfigs); return { schema, appConfigs, frontendConfig, frontendAppConfigs, fullConfig }; } catch (error) { const maybeSchemaError = error; if (maybeSchemaError.messages) { const messages = maybeSchemaError.messages.join("\n "); throw new Error(`Configuration does not match schema ${messages}`); } throw error; } } exports.createConfig = createConfig; exports.createScalprumConfig = createScalprumConfig; exports.isValidUrl = isValidUrl; exports.loadCliConfig = loadCliConfig; exports.resolveBaseUrl = resolveBaseUrl; exports.resolveBundlingPaths = resolveBundlingPaths; exports.run = run; exports.svgrTemplate = svgrTemplate; //# sourceMappingURL=config-fab10260.cjs.js.map