diff --git a/package.json b/package.json index 8bc2f1e99e..9cf989ca96 100644 --- a/package.json +++ b/package.json @@ -188,6 +188,8 @@ "@kubernetes/client-node": "^0.15.1", "@sentry/electron": "^2.5.4", "@sentry/integrations": "^6.15.0", + "@ogre-tools/injectable": "^1.2.1", + "@ogre-tools/injectable-react": "^1.2.1", "abort-controller": "^3.0.0", "auto-bind": "^4.0.0", "autobind-decorator": "^2.4.0", diff --git a/src/renderer/bootstrap.tsx b/src/renderer/bootstrap.tsx index 90e8c7fa95..edc4ff90f7 100644 --- a/src/renderer/bootstrap.tsx +++ b/src/renderer/bootstrap.tsx @@ -50,6 +50,9 @@ import { SentryInit } from "../common/sentry"; import { TerminalStore } from "./components/dock/terminal.store"; import { AppPaths } from "../common/app-paths"; import { registerCustomThemes } from "./components/monaco-editor"; +import { getDi } from "./components/getDi"; +import { DiContextProvider } from "@ogre-tools/injectable-react"; +import type { DependencyInjectionContainer } from "@ogre-tools/injectable"; if (process.isMainFrame) { SentryInit(); @@ -73,7 +76,7 @@ type AppComponent = React.ComponentType & { init(rootElem: HTMLElement): Promise; }; -export async function bootstrap(comp: () => Promise) { +export async function bootstrap(comp: () => Promise, di: DependencyInjectionContainer) { const rootElem = document.getElementById("app"); const logPrefix = `[BOOTSTRAP-${process.isMainFrame ? "ROOT" : "CLUSTER"}-FRAME]:`; @@ -147,17 +150,26 @@ export async function bootstrap(comp: () => Promise) { await App.init(rootElem); - render(<> - {isMac &&
} - {DefaultProps(App)} - , rootElem); + render( + + {isMac &&
} + + {DefaultProps(App)} + , + + rootElem, + ); } +const di = getDi(); + // run bootstrap( - async () => process.isMainFrame - ? (await import("./root-frame")).RootFrame - : (await import("./cluster-frame")).ClusterFrame, + async () => + process.isMainFrame + ? (await import("./root-frame")).RootFrame + : (await import("./cluster-frame")).ClusterFrame, + di, ); diff --git a/src/renderer/components/getDi.tsx b/src/renderer/components/getDi.tsx new file mode 100644 index 0000000000..65367a8c77 --- /dev/null +++ b/src/renderer/components/getDi.tsx @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import { createContainer } from "@ogre-tools/injectable"; +import type { ConfigurableDependencyInjectionContainer } from "@ogre-tools/injectable"; + +export const getDi = () => { + const di: ConfigurableDependencyInjectionContainer = createContainer( + () => require.context("./", true, /\.injectable\.(ts|tsx)$/), + ); + + return di; +}; diff --git a/src/renderer/components/getDiForUnitTesting.tsx b/src/renderer/components/getDiForUnitTesting.tsx new file mode 100644 index 0000000000..4e94d20dae --- /dev/null +++ b/src/renderer/components/getDiForUnitTesting.tsx @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import glob from "glob"; +import { memoize } from "lodash/fp"; + +import { + createContainer, + ConfigurableDependencyInjectionContainer, +} from "@ogre-tools/injectable"; + +export const getDiForUnitTesting = () => { + const di: ConfigurableDependencyInjectionContainer = createContainer(); + + getInjectableFilePaths() + .map(key => { + const injectable = require(key).default; + + return { + id: key, + ...injectable, + aliases: [injectable, ...(injectable.aliases || [])], + }; + }) + + .forEach(injectable => di.register(injectable)); + + di.preventSideEffects(); + + return di; +}; + +const getInjectableFilePaths = memoize(() => + glob.sync("./**/*.injectable.{ts,tsx}", { cwd: __dirname }), +); diff --git a/yarn.lock b/yarn.lock index a427e9f745..4be6fb2c11 100644 --- a/yarn.lock +++ b/yarn.lock @@ -946,6 +946,30 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" +"@ogre-tools/fp@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@ogre-tools/fp/-/fp-1.0.2.tgz#26c2c5cf60aa01cc94763cc68beba7052fdadfd9" + integrity sha512-ftvi/aoi5PaojWnuhHzp0YiecUd22HzW5gErsSiKyO2bps90WI4WjgY6d9hWdlzM9eukVmwM+dC6rGNlltNHNw== + dependencies: + lodash "^4.17.21" + +"@ogre-tools/injectable-react@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@ogre-tools/injectable-react/-/injectable-react-1.2.1.tgz#886fbb9f9816d68daf41b6fd7ff5def6eae833b4" + integrity sha512-kr9Q2T/VyhtUG8EbfzpFPk2ndwKQl9WHzqEfp8fasAXMNmUfUnyWs6iPNoJiuy2gh4/CNBvlFB8c647ls6/jUA== + dependencies: + "@ogre-tools/fp" "^1.0.2" + "@ogre-tools/injectable" "^1.2.1" + lodash "^4.17.21" + +"@ogre-tools/injectable@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@ogre-tools/injectable/-/injectable-1.2.1.tgz#f3eb481806dd6e53af8d9d37f8b20f3c0d875a60" + integrity sha512-bfTlnT08uDydE0i5GxJ9SIoRKfNYVabQRrZfBraZi2rs3zx+DOpcZrJjhjDoSCzIr6C2azySuyxn1h8x8CMUPw== + dependencies: + "@ogre-tools/fp" "^1.0.2" + lodash "^4.17.21" + "@panva/asn1.js@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@panva/asn1.js/-/asn1.js-1.0.0.tgz#dd55ae7b8129e02049f009408b97c61ccf9032f6"