diff --git a/packages/core/package.json b/packages/core/package.json index c343e3c0e6..f13f383437 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -44,7 +44,8 @@ "src/renderer/template.html", "templates/**/*", "types/*", - "tsconfig.json" + "tsconfig.json", + "src/renderer/**/*.svg" ], "copyright": "© 2023 OpenLens Authors", "license": "MIT", diff --git a/packages/core/src/renderer/bootstrap.tsx b/packages/core/src/renderer/bootstrap.tsx index f509847c74..d3e24754c0 100644 --- a/packages/core/src/renderer/bootstrap.tsx +++ b/packages/core/src/renderer/bootstrap.tsx @@ -13,12 +13,12 @@ import type { DiContainer } from "@ogre-tools/injectable"; import extensionLoaderInjectable from "../extensions/extension-loader/extension-loader.injectable"; import extensionDiscoveryInjectable from "../extensions/extension-discovery/extension-discovery.injectable"; import extensionInstallationStateStoreInjectable from "../extensions/extension-installation-state-store/extension-installation-state-store.injectable"; -import initRootFrameInjectable from "./frames/root-frame/init-root-frame.injectable"; -import initClusterFrameInjectable from "./frames/cluster-frame/init-cluster-frame/init-cluster-frame.injectable"; import { Router } from "react-router"; import historyInjectable from "./navigation/history.injectable"; import assert from "assert"; import startFrameInjectable from "./start-frame/start-frame.injectable"; +import rootComponentInjectable from "./bootstrap/root-component.injectable"; +import initializeAppInjectable from "./bootstrap/initialize-app.injectable"; export async function bootstrap(di: DiContainer) { const startFrame = di.inject(startFrameInjectable); @@ -41,17 +41,8 @@ export async function bootstrap(di: DiContainer) { extensionInstallationStateStore.bindIpcListeners(); - let App; - let initializeApp; - - // TODO: Introduce proper architectural boundaries between root and cluster iframes - if (process.isMainFrame) { - initializeApp = di.inject(initRootFrameInjectable); - App = (await import("./frames/root-frame/root-frame")).RootFrame; - } else { - initializeApp = di.inject(initClusterFrameInjectable); - App = (await import("./frames/cluster-frame/cluster-frame")).ClusterFrame; - } + const App = di.inject(rootComponentInjectable); + const initializeApp = di.inject(initializeAppInjectable); try { await initializeApp(() => unmountComponentAtNode(rootElem)); diff --git a/packages/core/src/renderer/bootstrap/initialize-app.injectable.ts b/packages/core/src/renderer/bootstrap/initialize-app.injectable.ts new file mode 100644 index 0000000000..fd90d92c1d --- /dev/null +++ b/packages/core/src/renderer/bootstrap/initialize-app.injectable.ts @@ -0,0 +1,32 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { initializeAppInjectionToken } from "./tokens"; + +const initializeAppInjectable = getInjectable({ + id: "initialize-app", + instantiate: (di) => { + const options = di.injectMany(initializeAppInjectionToken); + + if (options.length === 0) { + throw new Error("No intializeApp registered"); + } + + const intializeApp = options.find(opt => opt.isActive); + const howManyActive = options.reduce((count, cur) => count + +cur.isActive, 0); + + if (!intializeApp) { + throw new Error("No initializeApp registrations are active"); + } + + if (howManyActive > 1) { + throw new Error("Too many initiazlizeApp registrations are active"); + } + + return intializeApp.init; + }, +}); + +export default initializeAppInjectable; diff --git a/packages/core/src/renderer/bootstrap/root-component.injectable.ts b/packages/core/src/renderer/bootstrap/root-component.injectable.ts new file mode 100644 index 0000000000..511c9ee70c --- /dev/null +++ b/packages/core/src/renderer/bootstrap/root-component.injectable.ts @@ -0,0 +1,32 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { rootComponentInjectionToken } from "./tokens"; + +const rootComponentInjectable = getInjectable({ + id: "root-component", + instantiate: (di) => { + const options = di.injectMany(rootComponentInjectionToken); + + if (options.length === 0) { + throw new Error("No intializeApp registered"); + } + + const intializeApp = options.find(opt => opt.isActive); + const howManyActive = options.reduce((count, cur) => count + +cur.isActive, 0); + + if (!intializeApp) { + throw new Error("No initializeApp registrations are active"); + } + + if (howManyActive > 1) { + throw new Error("Too many initiazlizeApp registrations are active"); + } + + return intializeApp.Component; + }, +}); + +export default rootComponentInjectable; diff --git a/packages/core/src/renderer/bootstrap/tokens.ts b/packages/core/src/renderer/bootstrap/tokens.ts new file mode 100644 index 0000000000..1add7ba16b --- /dev/null +++ b/packages/core/src/renderer/bootstrap/tokens.ts @@ -0,0 +1,25 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import { getInjectionToken } from "@ogre-tools/injectable"; +import type { FunctionComponent } from "react"; + +export interface InitializeApp { + init: (unmountRoot: () => void) => Promise; + isActive: boolean; +} + +export const initializeAppInjectionToken = getInjectionToken({ + id: "initialize-app-token", +}); + +export interface RootComponent { + Component: FunctionComponent<{}>; + isActive: boolean; +} + +export const rootComponentInjectionToken = getInjectionToken({ + id: "root-component-token", +}); diff --git a/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.injectable.ts b/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.injectable.ts index c640264ee3..567ac12470 100644 --- a/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.injectable.ts +++ b/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.injectable.ts @@ -7,30 +7,28 @@ import { initClusterFrame } from "./init-cluster-frame"; import catalogEntityRegistryInjectable from "../../../api/catalog/entity/registry.injectable"; import frameRoutingIdInjectable from "./frame-routing-id/frame-routing-id.injectable"; import hostedClusterInjectable from "../../../cluster-frame-context/hosted-cluster.injectable"; -import assert from "assert"; import emitAppEventInjectable from "../../../../common/app-event-bus/emit-event.injectable"; import loadExtensionsInjectable from "../../load-extensions.injectable"; import loggerInjectable from "../../../../common/logger.injectable"; import showErrorNotificationInjectable from "../../../components/notifications/show-error-notification.injectable"; +import { initializeAppInjectionToken } from "../../../bootstrap/tokens"; const initClusterFrameInjectable = getInjectable({ id: "init-cluster-frame", - instantiate: (di) => { - const hostedCluster = di.inject(hostedClusterInjectable); - - assert(hostedCluster, "This can only be injected within a cluster frame"); - - return initClusterFrame({ - hostedCluster, + instantiate: (di) => ({ + init: initClusterFrame({ + hostedCluster: di.inject(hostedClusterInjectable), loadExtensions: di.inject(loadExtensionsInjectable), catalogEntityRegistry: di.inject(catalogEntityRegistryInjectable), frameRoutingId: di.inject(frameRoutingIdInjectable), emitAppEvent: di.inject(emitAppEventInjectable), logger: di.inject(loggerInjectable), showErrorNotification: di.inject(showErrorNotificationInjectable), - }); - }, + }), + isActive: !process.isMainFrame, + }), + injectionToken: initializeAppInjectionToken, }); export default initClusterFrameInjectable; diff --git a/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.ts b/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.ts index 109ae0f0bc..6b44eae2a1 100644 --- a/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.ts +++ b/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame/init-cluster-frame.ts @@ -9,9 +9,10 @@ import { when } from "mobx"; import { requestSetClusterFrameId } from "../../../ipc"; import type { EmitAppEvent } from "../../../../common/app-event-bus/emit-event.injectable"; import type { Logger } from "../../../../common/logger"; +import assert from "assert"; interface Dependencies { - hostedCluster: Cluster; + hostedCluster: Cluster | undefined; loadExtensions: () => void; catalogEntityRegistry: CatalogEntityRegistry; frameRoutingId: number; @@ -32,6 +33,8 @@ export const initClusterFrame = ({ showErrorNotification, }: Dependencies) => async (unmountRoot: () => void) => { + assert(hostedCluster, "This can only be injected within a cluster frame"); + // TODO: Make catalogEntityRegistry already initialized when passed as dependency catalogEntityRegistry.init(); diff --git a/packages/core/src/renderer/frames/cluster-frame/root-component.injectable.ts b/packages/core/src/renderer/frames/cluster-frame/root-component.injectable.ts new file mode 100644 index 0000000000..0df1fa9783 --- /dev/null +++ b/packages/core/src/renderer/frames/cluster-frame/root-component.injectable.ts @@ -0,0 +1,18 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { rootComponentInjectionToken } from "../../bootstrap/tokens"; +import { ClusterFrame } from "./cluster-frame"; + +const clusterFrameRootComponentInjectable = getInjectable({ + id: "cluster-frame-root-component", + instantiate: () => ({ + Component: ClusterFrame, + isActive: !process.isMainFrame, + }), + injectionToken: rootComponentInjectionToken, +}); + +export default clusterFrameRootComponentInjectable; diff --git a/packages/core/src/renderer/frames/root-frame/init-root-frame.injectable.ts b/packages/core/src/renderer/frames/root-frame/init-root-frame.injectable.ts index 8d2c3a43be..c47e77fbf7 100644 --- a/packages/core/src/renderer/frames/root-frame/init-root-frame.injectable.ts +++ b/packages/core/src/renderer/frames/root-frame/init-root-frame.injectable.ts @@ -13,19 +13,20 @@ import loggerInjectable from "../../../common/logger.injectable"; import { delay } from "../../../common/utils"; import { broadcastMessage } from "../../../common/ipc"; import { bundledExtensionsLoaded } from "../../../common/ipc/extension-handling"; +import { initializeAppInjectionToken } from "../../bootstrap/tokens"; const initRootFrameInjectable = getInjectable({ id: "init-root-frame", - instantiate: (di) => { - const loadExtensions = di.inject(loadExtensionsInjectable); - const registerIpcListeners = di.inject(registerIpcListenersInjectable); - const ipcRenderer = di.inject(ipcRendererInjectable); - const bindProtocolAddRouteHandlers = di.inject(bindProtocolAddRouteHandlersInjectable); - const lensProtocolRouterRenderer = di.inject(lensProtocolRouterRendererInjectable); - const catalogEntityRegistry = di.inject(catalogEntityRegistryInjectable); - const logger = di.inject(loggerInjectable); + instantiate: (di) => ({ + init: async (unmountRoot: () => void) => { + const loadExtensions = di.inject(loadExtensionsInjectable); + const registerIpcListeners = di.inject(registerIpcListenersInjectable); + const ipcRenderer = di.inject(ipcRendererInjectable); + const bindProtocolAddRouteHandlers = di.inject(bindProtocolAddRouteHandlersInjectable); + const lensProtocolRouterRenderer = di.inject(lensProtocolRouterRendererInjectable); + const catalogEntityRegistry = di.inject(catalogEntityRegistryInjectable); + const logger = di.inject(loggerInjectable); - return async (unmountRoot: () => void) => { catalogEntityRegistry.init(); try { @@ -49,8 +50,7 @@ const initRootFrameInjectable = getInjectable({ bindProtocolAddRouteHandlers(); - window.addEventListener("offline", () => - broadcastMessage("network:offline"), + window.addEventListener("offline", () => broadcastMessage("network:offline"), ); window.addEventListener("online", () => broadcastMessage("network:online")); @@ -62,8 +62,10 @@ const initRootFrameInjectable = getInjectable({ unmountRoot(); }); - }; - }, + }, + isActive: process.isMainFrame, + }), + injectionToken: initializeAppInjectionToken, }); export default initRootFrameInjectable; diff --git a/packages/core/src/renderer/frames/root-frame/root-component.injectable.ts b/packages/core/src/renderer/frames/root-frame/root-component.injectable.ts new file mode 100644 index 0000000000..ad81c51e5d --- /dev/null +++ b/packages/core/src/renderer/frames/root-frame/root-component.injectable.ts @@ -0,0 +1,18 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { rootComponentInjectionToken } from "../../bootstrap/tokens"; +import { RootFrame } from "./root-frame"; + +const rootFrameRootComponentInjectable = getInjectable({ + id: "root-frame-root-component", + instantiate: () => ({ + Component: RootFrame, + isActive: process.isMainFrame, + }), + injectionToken: rootComponentInjectionToken, +}); + +export default rootFrameRootComponentInjectable; diff --git a/packages/core/webpack/common.ts b/packages/core/webpack/common.ts index 2f5672c94a..e42a688239 100644 --- a/packages/core/webpack/common.ts +++ b/packages/core/webpack/common.ts @@ -6,32 +6,27 @@ import type webpack from "webpack"; import path from "path"; import ForkTsCheckerPlugin from "fork-ts-checker-webpack-plugin"; -import webpackLensMain from "./main"; +import { webpackLensMain } from "./main"; import { buildDir } from "./vars"; -const webpackLensCommon = (): webpack.Configuration => { - const mainConfig = webpackLensMain(); - - return { - ...mainConfig, - name: "lens-app-common", - entry: { - common: path.resolve(__dirname, "..", "src", "common", "library.ts"), +export const webpackLensCommon = (): webpack.Configuration => ({ + ...webpackLensMain(), + name: "lens-app-common", + entry: { + common: path.resolve(__dirname, "..", "src", "common", "library.ts"), + }, + dependencies: [], + output: { + publicPath: "", + library: { + type: "commonjs2", }, - output: { - publicPath: "", - library: { - type: "commonjs2", - }, - path: path.resolve(buildDir, "library"), - }, - optimization: { - minimize: false, - }, - plugins: [ - new ForkTsCheckerPlugin({}), - ], - }; -}; - -export default webpackLensCommon; + path: path.resolve(buildDir, "library"), + }, + optimization: { + minimize: false, + }, + plugins: [ + new ForkTsCheckerPlugin({}), + ], +}); diff --git a/packages/core/webpack/library-bundle.ts b/packages/core/webpack/library-bundle.ts index 78d7be1bd4..095772c688 100644 --- a/packages/core/webpack/library-bundle.ts +++ b/packages/core/webpack/library-bundle.ts @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import webpackLensCommon from "./common"; -import webpackLensMain from "./main"; +import { webpackLensCommon } from "./common"; +import { webpackLensMain } from "./main"; import { webpackLensRenderer } from "./renderer"; const config = [ diff --git a/packages/core/webpack/main.ts b/packages/core/webpack/main.ts index ea93bcd30d..7e96ab2f67 100755 --- a/packages/core/webpack/main.ts +++ b/packages/core/webpack/main.ts @@ -12,76 +12,81 @@ import { DefinePlugin } from "webpack"; import { buildDir, isDevelopment } from "./vars"; import { platform } from "process"; -const webpackLensMain = (): webpack.Configuration => { - return { - name: "lens-app-main", - context: __dirname, - target: "electron-main", - mode: isDevelopment ? "development" : "production", - devtool: isDevelopment ? "cheap-module-source-map" : "source-map", - cache: isDevelopment ? { type: "filesystem" } : false, - entry: { - main: path.resolve(__dirname, "..", "src", "main", "library.ts"), +export const webpackLensMain = (): webpack.Configuration => ({ + name: "lens-app-main", + context: __dirname, + target: "electron-main", + mode: isDevelopment ? "development" : "production", + devtool: isDevelopment ? "cheap-module-source-map" : "source-map", + cache: isDevelopment ? { type: "filesystem" } : false, + entry: { + common: { + import: path.resolve(__dirname, "..", "static", "build", "library", "common.js"), }, - output: { - library: { - type: "commonjs2", + main: { + import: path.resolve(__dirname, "..", "src", "main", "library.ts"), + dependOn: "common", + }, + }, + dependencies: [ + "lens-app-common", + ], + output: { + library: { + type: "commonjs2", + }, + path: path.resolve(buildDir, "library"), + }, + optimization: { + minimize: false, + }, + resolve: { + extensions: [".json", ".js", ".ts"], + }, + externals: [ + nodeExternals(), + ], + module: { + parser: { + javascript: { + commonjsMagicComments: true, }, - path: path.resolve(buildDir, "library"), }, - optimization: { - minimize: false, - }, - resolve: { - extensions: [".json", ".js", ".ts"], - }, - externals: [ - nodeExternals(), - ], - module: { - parser: { - javascript: { - commonjsMagicComments: true, - }, + rules: [ + { + test: /\.node$/, + use: "node-loader", }, - rules: [ - { - test: /\.node$/, - use: "node-loader", - }, - { - test: /\.ts$/, - exclude: /node_modules/, - use: { - loader: "ts-loader", - options: { - transpileOnly: true, - compilerOptions: { - sourceMap: false, - }, - }, - }, - }, - ...iconsAndImagesWebpackRules(), - ], - }, - plugins: [ - new DefinePlugin({ - CONTEXT_MATCHER_FOR_NON_FEATURES: `/\\.injectable(\\.${platform})?\\.tsx?$/`, - CONTEXT_MATCHER_FOR_FEATURES: `/\\/(main|common)\\/.+\\.injectable(\\.${platform})?\\.tsx?$/`, - }), - new ForkTsCheckerPlugin({ - typescript: { - mode: "write-dts", - configOverwrite: { + { + test: /\.ts$/, + exclude: /node_modules/, + use: { + loader: "ts-loader", + options: { + transpileOnly: true, compilerOptions: { - declaration: true, + sourceMap: false, }, }, }, - }), + }, + ...iconsAndImagesWebpackRules(), ], - }; -}; - -export default webpackLensMain; + }, + plugins: [ + new DefinePlugin({ + CONTEXT_MATCHER_FOR_NON_FEATURES: `/\\.injectable(\\.${platform})?\\.tsx?$/`, + CONTEXT_MATCHER_FOR_FEATURES: `/\\/(main|common)\\/.+\\.injectable(\\.${platform})?\\.tsx?$/`, + }), + new ForkTsCheckerPlugin({ + typescript: { + mode: "write-dts", + configOverwrite: { + compilerOptions: { + declaration: true, + }, + }, + }, + }), + ], +}); diff --git a/packages/core/webpack/renderer.ts b/packages/core/webpack/renderer.ts index d5bddf6461..7c27f6decd 100755 --- a/packages/core/webpack/renderer.ts +++ b/packages/core/webpack/renderer.ts @@ -14,97 +14,104 @@ import nodeExternals from "webpack-node-externals"; import { isDevelopment, buildDir, sassCommonVars } from "./vars"; import { platform } from "process"; -export function webpackLensRenderer(): webpack.Configuration { - return { - target: "electron-renderer", - name: "lens-app-renderer", - mode: isDevelopment ? "development" : "production", - // https://webpack.js.org/configuration/devtool/ (see description of each option) - devtool: isDevelopment ? "cheap-module-source-map" : "source-map", - cache: isDevelopment ? { type: "filesystem" } : false, - entry: { - renderer: path.resolve(__dirname, "..", "src", "renderer", "library.ts"), +export const webpackLensRenderer = (): webpack.Configuration => ({ + target: "electron-renderer", + name: "lens-app-renderer", + mode: isDevelopment ? "development" : "production", + // https://webpack.js.org/configuration/devtool/ (see description of each option) + devtool: isDevelopment ? "cheap-module-source-map" : "source-map", + cache: isDevelopment ? { type: "filesystem" } : false, + entry: { + common: { + import: path.resolve(__dirname, "..", "static", "build", "library", "common.js"), }, - output: { - library: { - type: "commonjs2", - }, - path: path.resolve(buildDir, "library"), + renderer: { + import: path.resolve(__dirname, "..", "src", "renderer", "library.ts"), + dependOn: "common", }, - watchOptions: { - ignored: /node_modules/, // https://webpack.js.org/configuration/watch/ + }, + dependencies: [ + "lens-app-common", + ], + output: { + library: { + type: "commonjs2", }, - ignoreWarnings: [ - /Critical dependency: the request of a dependency is an expression/, - /require.extensions is not supported by webpack./, // handlebars - /\[ReactRefreshPlugin] .*?HMR.*? is not enabled/, // enabled in webpack.dev-server + path: path.resolve(buildDir, "library"), + }, + watchOptions: { + ignored: /node_modules/, // https://webpack.js.org/configuration/watch/ + }, + ignoreWarnings: [ + /Critical dependency: the request of a dependency is an expression/, + /require.extensions is not supported by webpack./, + /\[ReactRefreshPlugin] .*?HMR.*? is not enabled/, // enabled in webpack.dev-server + ], + resolve: { + extensions: [ + ".js", ".jsx", ".json", + ".ts", ".tsx", ], - resolve: { - extensions: [ - ".js", ".jsx", ".json", - ".ts", ".tsx", - ], - }, - externals: [ - nodeExternals(), - ], - optimization: { - minimize: false, - }, - module: { - parser: { - javascript: { - commonjsMagicComments: true, - }, + }, + externals: [ + nodeExternals(), + ], + optimization: { + minimize: false, + }, + module: { + parser: { + javascript: { + commonjsMagicComments: true, }, - rules: [ - { - test: /\.node$/, - use: "node-loader", - }, - { - test: /\.tsx?$/, - exclude: /node_modules/, - use: { - loader: "ts-loader", - options: { - transpileOnly: true, - compilerOptions: { - declaration: true, - sourceMap: false, - }, + }, + rules: [ + { + test: /\.node$/, + use: "node-loader", + }, + { + test: /\.tsx?$/, + exclude: /node_modules/, + use: { + loader: "ts-loader", + options: { + transpileOnly: true, + compilerOptions: { + declaration: true, + sourceMap: false, }, }, }, - cssModulesWebpackRule(), - ...iconsAndImagesWebpackRules(), - ...fontsLoaderWebpackRules(), - ], - }, - - plugins: [ - new DefinePlugin({ - CONTEXT_MATCHER_FOR_NON_FEATURES: `/\\.injectable(\\.${platform})?\\.tsx?$/`, - CONTEXT_MATCHER_FOR_FEATURES: `/\\/(renderer|common)\\/.+\\.injectable(\\.${platform})?\\.tsx?$/`, - }), - new ForkTsCheckerPlugin({}), - - new CircularDependencyPlugin({ - cwd: __dirname, - exclude: /node_modules/, - failOnError: true, - }) as unknown as WebpackPluginInstance, - - new MiniCssExtractPlugin({ - filename: "[name].css", - }), - - new optimize.LimitChunkCountPlugin({ - maxChunks: 1, - }), + }, + cssModulesWebpackRule(), + ...iconsAndImagesWebpackRules(), + ...fontsLoaderWebpackRules(), ], - }; -} + }, + + plugins: [ + new DefinePlugin({ + CONTEXT_MATCHER_FOR_NON_FEATURES: `/\\.injectable(\\.${platform})?\\.tsx?$/`, + CONTEXT_MATCHER_FOR_FEATURES: `/\\/(renderer|common)\\/.+\\.injectable(\\.${platform})?\\.tsx?$/`, + }), + new ForkTsCheckerPlugin({}), + + new CircularDependencyPlugin({ + cwd: __dirname, + exclude: /node_modules/, + failOnError: true, + }) as unknown as WebpackPluginInstance, + + new MiniCssExtractPlugin({ + filename: "[name].css", + }), + + new optimize.LimitChunkCountPlugin({ + maxChunks: 1, + }), + ], +}); /** * Import icons and image files. diff --git a/packages/open-lens/package.json b/packages/open-lens/package.json index 330c529fd8..f70c1025ca 100644 --- a/packages/open-lens/package.json +++ b/packages/open-lens/package.json @@ -258,6 +258,7 @@ "react-select": "^5.7.0", "rimraf": "^4.1.2", "run-script-os": "^1.1.6", + "source-map-loader": "^4.0.1", "style-loader": "^3.3.1", "tailwindcss": "^3.2.4", "ts-loader": "^9.4.2", diff --git a/packages/open-lens/webpack/renderer.ts b/packages/open-lens/webpack/renderer.ts index cf2104053e..6c5824a498 100644 --- a/packages/open-lens/webpack/renderer.ts +++ b/packages/open-lens/webpack/renderer.ts @@ -11,7 +11,7 @@ import MonacoWebpackPlugin from "monaco-editor-webpack-plugin"; import CircularDependencyPlugin from "circular-dependency-plugin"; import ReactRefreshWebpackPlugin from "@pmmmwh/react-refresh-webpack-plugin"; - import type { WebpackPluginInstance } from "webpack"; + import { WebpackPluginInstance } from "webpack"; import { DefinePlugin } from "webpack"; import { assetsFolderName, isDevelopment, rendererDir, buildDir, htmlTemplate, publicPath, sassCommonVars } from "./vars"; import { platform } from "process"; @@ -42,6 +42,7 @@ /Critical dependency: the request of a dependency is an expression/, /require.extensions is not supported by webpack./, // handlebars /\[ReactRefreshPlugin] .*?HMR.*? is not enabled/, // enabled in webpack.dev-server + /Failed to parse source map/, // from the source-map-loader ], resolve: { extensions: [ @@ -68,9 +69,18 @@ use: "node-loader", }, { - test: /\.tsx?$/, - loader: "ts-loader", - options: {}, + test: /\.tsx?$/, + loader: "ts-loader", + options: {}, + }, + { + test: /\.js$/, + enforce: "pre", + use: [ + { + loader: "source-map-loader", + } + ], }, cssModulesWebpackRule(), ...iconsAndImagesWebpackRules(), diff --git a/packages/open-lens/yarn.lock b/packages/open-lens/yarn.lock index 0eb1d19857..e119877c2f 100644 --- a/packages/open-lens/yarn.lock +++ b/packages/open-lens/yarn.lock @@ -9815,6 +9815,15 @@ source-list-map@^2.0.1: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +source-map-loader@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-4.0.1.tgz#72f00d05f5d1f90f80974eda781cbd7107c125f2" + integrity sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA== + dependencies: + abab "^2.0.6" + iconv-lite "^0.6.3" + source-map-js "^1.0.2" + source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"