diff --git a/RELEASE_GUIDE.md b/RELEASE_GUIDE.md index 01969bbbee..338d7154e9 100644 --- a/RELEASE_GUIDE.md +++ b/RELEASE_GUIDE.md @@ -11,9 +11,12 @@ All releases will be made by creating a PR which bumps the version field in the ## Steps -1. If you are making a minor or major release (or prereleases for one) make sure you are on the `master` branch. +1. If you are making a minor or major release (or prereleases of one) make sure you are on the `master` branch. 1. If you are making a patch release (or a prerelease for one) make sure you are on the `release/v.` branch. -1. Run `npm run create-release-pr `. If you are making a subsequent prerelease release, provide the `--check-commits` flag. -1. If you are checking the commits, type `y` to pick a commit, and `n` to skip it. You will want to skip the commits that were part of previous prerelease releases. +1. Run `npm run create-release-pr`. +1. Pick the PRs that you want to include in this release using the keys listed. 1. Once the PR is created, approved, and then merged the `Release Open Lens` workflow will create a tag and release for you. 1. If you are making a major or minor release, create a `release/v.` branch and push it to `origin` so that future patch releases can be made from it. +1. If you released a major or minor version, create a new patch milestone and move all bug issues to that milestone and all enhancement issues to the next minor milestone. +1. If you released a patch version, create a new patch milestone for the next patch version and move all the issues and PRs (open or closed) that weren't included in the current release to that milestone. +1. Close the milestone related to the release that was just made (if not a prerelease release). diff --git a/package.json b/package.json index d43a8726e6..43cd21522b 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,6 @@ "adr": "^1.4.3", "cross-env": "^7.0.3", "lerna": "^6.5.1", - "rimraf": "^4.1.3" + "rimraf": "^4.2.0" } } diff --git a/packages/bump-version-for-cron/package.json b/packages/bump-version-for-cron/package.json index 484b4d1102..206415fba6 100644 --- a/packages/bump-version-for-cron/package.json +++ b/packages/bump-version-for-cron/package.json @@ -23,7 +23,7 @@ }, "devDependencies": { "@swc/cli": "^0.1.61", - "@swc/core": "^1.3.35", + "@swc/core": "^1.3.37", "@types/node": "^16.18.11", "@types/semver": "^7.3.13", "rimraf": "^4.1.2" diff --git a/packages/core/package.json b/packages/core/package.json index 468763de3b..07f06ab022 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -130,11 +130,12 @@ "@k8slens/node-fetch": "^6.5.0-alpha.0", "@kubernetes/client-node": "^0.18.1", "@material-ui/styles": "^4.11.5", - "@ogre-tools/fp": "^15.1.1", - "@ogre-tools/injectable": "^15.1.1", - "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.1", - "@ogre-tools/injectable-extension-for-mobx": "^15.1.1", - "@ogre-tools/injectable-react": "^15.1.1", + "@ogre-tools/fp": "^15.1.2", + "@ogre-tools/injectable": "^15.1.2", + "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", + "@ogre-tools/injectable-extension-for-mobx": "^15.1.2", + "@ogre-tools/injectable-react": "^15.1.2", + "@ogre-tools/injectable-utils": "^15.1.2", "@sentry/electron": "^3.0.8", "@sentry/integrations": "^6.19.3", "@side/jest-runtime": "^1.1.0", @@ -202,7 +203,7 @@ "@material-ui/lab": "^4.0.0-alpha.60", "@sentry/types": "^6.19.7", "@swc/cli": "^0.1.61", - "@swc/core": "^1.3.35", + "@swc/core": "^1.3.37", "@swc/jest": "^0.2.24", "@testing-library/dom": "^7.31.2", "@testing-library/jest-dom": "^5.16.5", @@ -330,6 +331,7 @@ }, "peerDependencies": { "@k8slens/application": "^6.5.0-alpha.0", + "@k8slens/application-for-electron-main": "^6.5.0-alpha.0", "@k8slens/run-many": "^1.0.0", "@k8slens/test-utils": "^1.0.0", "@k8slens/utilities": "^1.0.0", diff --git a/packages/core/src/common/cluster/cluster.ts b/packages/core/src/common/cluster/cluster.ts index 53c6a8a88b..06fb5f06d2 100644 --- a/packages/core/src/common/cluster/cluster.ts +++ b/packages/core/src/common/cluster/cluster.ts @@ -700,6 +700,11 @@ export class Cluster implements ClusterModel { } shouldShowResource(resource: KubeApiResourceDescriptor): boolean { + if (this.allowedResources.size === 0) { + // better to show than hide everything + return true; + } + return this.allowedResources.has(formatKubeApiResource(resource)); } diff --git a/packages/core/src/common/create-app.ts b/packages/core/src/common/create-app.ts deleted file mode 100644 index 2696950ce7..0000000000 --- a/packages/core/src/common/create-app.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import type { DiContainerForInjection } from "@ogre-tools/injectable"; - -export interface ApplicationConfig { - mode: string; -} - -export interface Application { - start: () => Promise; - readonly di: DiContainerForInjection; -} - -export type CreateApplication = (config: ApplicationConfig) => Application; diff --git a/packages/core/src/common/vars/is-production.injectable.ts b/packages/core/src/common/vars/is-production.injectable.ts index 661cb397d1..9c1d036bee 100644 --- a/packages/core/src/common/vars/is-production.injectable.ts +++ b/packages/core/src/common/vars/is-production.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import nodeEnvInjectionToken from "./node-env-injection-token"; +import { nodeEnvInjectionToken } from "./node-env-injection-token"; const isProductionInjectable = getInjectable({ id: "is-production", diff --git a/packages/core/src/common/vars/node-env-injection-token.ts b/packages/core/src/common/vars/node-env-injection-token.ts index 9de463c1cb..5f50ad2e06 100644 --- a/packages/core/src/common/vars/node-env-injection-token.ts +++ b/packages/core/src/common/vars/node-env-injection-token.ts @@ -4,7 +4,7 @@ */ import { getInjectionToken } from "@ogre-tools/injectable"; -const nodeEnvInjectionToken = getInjectionToken({ +export const nodeEnvInjectionToken = getInjectionToken({ id: "node-env-injection-token", }); diff --git a/packages/core/src/common/vars/node-env.injectable.testing-env.ts b/packages/core/src/common/vars/node-env.injectable.testing-env.ts index 29231a4010..20d041330f 100644 --- a/packages/core/src/common/vars/node-env.injectable.testing-env.ts +++ b/packages/core/src/common/vars/node-env.injectable.testing-env.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import nodeEnvInjectionToken from "./node-env-injection-token"; +import { nodeEnvInjectionToken } from "./node-env-injection-token"; const nodeEnvFakeInjectable = getInjectable({ id: "node-env-fake", diff --git a/packages/core/src/features/application-menu/main/start-application-menu.injectable.ts b/packages/core/src/features/application-menu/main/start-application-menu.injectable.ts index 13fd8e4938..6f7c2132bc 100644 --- a/packages/core/src/features/application-menu/main/start-application-menu.injectable.ts +++ b/packages/core/src/features/application-menu/main/start-application-menu.injectable.ts @@ -4,18 +4,20 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import applicationMenuReactivityInjectable from "./application-menu-reactivity.injectable"; -import { onLoadOfApplicationInjectionToken } from "../../../main/start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const startApplicationMenuInjectable = getInjectable({ id: "start-application-menu", - instantiate: (di) => ({ - run: () => { - const applicationMenu = di.inject(applicationMenuReactivityInjectable); + instantiate: (di) => { + const applicationMenu = di.inject(applicationMenuReactivityInjectable); - applicationMenu.start(); - }, - }), + return { + run: () => { + applicationMenu.start(); + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/start-checking-for-updates.injectable.ts b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/start-checking-for-updates.injectable.ts index fa129f8522..c6e5038bcf 100644 --- a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/start-checking-for-updates.injectable.ts +++ b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/start-checking-for-updates.injectable.ts @@ -5,21 +5,23 @@ import { getInjectable } from "@ogre-tools/injectable"; import periodicalCheckForUpdatesInjectable from "./periodical-check-for-updates.injectable"; import updatingIsEnabledInjectable from "../../../main/updating-is-enabled/updating-is-enabled.injectable"; -import { afterApplicationIsLoadedInjectionToken } from "../../../../../main/start-main-application/runnable-tokens/phases"; +import { afterApplicationIsLoadedInjectionToken } from "@k8slens/application"; const startCheckingForUpdatesInjectable = getInjectable({ id: "start-checking-for-updates", - instantiate: (di) => ({ - run: () => { - const periodicalCheckForUpdates = di.inject(periodicalCheckForUpdatesInjectable); - const updatingIsEnabled = di.inject(updatingIsEnabledInjectable); + instantiate: (di) => { + const periodicalCheckForUpdates = di.inject(periodicalCheckForUpdatesInjectable); + const updatingIsEnabled = di.inject(updatingIsEnabledInjectable); - if (updatingIsEnabled && !periodicalCheckForUpdates.started) { - periodicalCheckForUpdates.start(); - } - }, - }), + return { + run: () => { + if (updatingIsEnabled && !periodicalCheckForUpdates.started) { + periodicalCheckForUpdates.start(); + } + }, + }; + }, injectionToken: afterApplicationIsLoadedInjectionToken, }); diff --git a/packages/core/src/features/application-update/main/emit-current-version-to-analytics.injectable.ts b/packages/core/src/features/application-update/main/emit-current-version-to-analytics.injectable.ts index b976b78625..d07a723b3d 100644 --- a/packages/core/src/features/application-update/main/emit-current-version-to-analytics.injectable.ts +++ b/packages/core/src/features/application-update/main/emit-current-version-to-analytics.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { afterApplicationIsLoadedInjectionToken } from "../../../main/start-main-application/runnable-tokens/phases"; +import { afterApplicationIsLoadedInjectionToken } from "@k8slens/application"; import emitAppEventInjectable from "../../../common/app-event-bus/emit-event.injectable"; import { getCurrentDateTime } from "../../../common/utils/date/get-current-date-time"; import buildVersionInjectable from "../../../main/vars/build-version/build-version.injectable"; @@ -11,22 +11,24 @@ import buildVersionInjectable from "../../../main/vars/build-version/build-versi const emitCurrentVersionToAnalyticsInjectable = getInjectable({ id: "emit-current-version-to-analytics", - instantiate: (di) => ({ - run: () => { - const emitAppEvent = di.inject(emitAppEventInjectable); - const buildVersion = di.inject(buildVersionInjectable); + instantiate: (di) => { + const emitAppEvent = di.inject(emitAppEventInjectable); + const buildVersion = di.inject(buildVersionInjectable); - emitAppEvent({ - name: "app", - action: "current-version", + return { + run: () => { + emitAppEvent({ + name: "app", + action: "current-version", - params: { - version: buildVersion.get(), - currentDateTime: getCurrentDateTime(), - }, - }); - }, - }), + params: { + version: buildVersion.get(), + currentDateTime: getCurrentDateTime(), + }, + }); + }, + }; + }, injectionToken: afterApplicationIsLoadedInjectionToken, }); diff --git a/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/start-watching-if-update-should-happen-on-quit.injectable.ts b/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/start-watching-if-update-should-happen-on-quit.injectable.ts index f540c9f082..7359b3bb49 100644 --- a/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/start-watching-if-update-should-happen-on-quit.injectable.ts +++ b/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/start-watching-if-update-should-happen-on-quit.injectable.ts @@ -3,19 +3,21 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { onLoadOfApplicationInjectionToken } from "../../../../main/start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; import watchIfUpdateShouldHappenOnQuitInjectable from "./watch-if-update-should-happen-on-quit.injectable"; const startWatchingIfUpdateShouldHappenOnQuitInjectable = getInjectable({ id: "start-watching-if-update-should-happen-on-quit", - instantiate: (di) => ({ - run: () => { - const watchIfUpdateShouldHappenOnQuit = di.inject(watchIfUpdateShouldHappenOnQuitInjectable); + instantiate: (di) => { + const watchIfUpdateShouldHappenOnQuit = di.inject(watchIfUpdateShouldHappenOnQuitInjectable); - watchIfUpdateShouldHappenOnQuit.start(); - }, - }), + return { + run: () => { + watchIfUpdateShouldHappenOnQuit.start(); + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/features/cluster/state-sync/main/setup-sync.injectable.ts b/packages/core/src/features/cluster/state-sync/main/setup-sync.injectable.ts index b161d57b5c..348450958d 100644 --- a/packages/core/src/features/cluster/state-sync/main/setup-sync.injectable.ts +++ b/packages/core/src/features/cluster/state-sync/main/setup-sync.injectable.ts @@ -7,7 +7,7 @@ import { isEqual } from "lodash"; import { autorun } from "mobx"; import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable"; import type { ClusterId, ClusterState } from "../../../../common/cluster-types"; -import { beforeApplicationIsLoadingInjectionToken } from "../../../../main/start-main-application/runnable-tokens/phases"; +import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application"; import initClusterStoreInjectable from "../../store/main/init.injectable"; import emitClusterStateUpdateInjectable from "./emit-update.injectable"; diff --git a/packages/core/src/features/cluster/store/main/init.injectable.ts b/packages/core/src/features/cluster/store/main/init.injectable.ts index b98dec70b7..07bc4451f6 100644 --- a/packages/core/src/features/cluster/store/main/init.injectable.ts +++ b/packages/core/src/features/cluster/store/main/init.injectable.ts @@ -4,19 +4,21 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable"; -import { beforeApplicationIsLoadingInjectionToken } from "../../../../main/start-main-application/runnable-tokens/phases"; +import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application"; import initUserStoreInjectable from "../../../../main/stores/init-user-store.injectable"; const initClusterStoreInjectable = getInjectable({ id: "init-cluster-store", - instantiate: (di) => ({ - run: () => { - const clusterStore = di.inject(clusterStoreInjectable); + instantiate: (di) => { + const clusterStore = di.inject(clusterStoreInjectable); - clusterStore.load(); - }, - runAfter: initUserStoreInjectable, - }), + return { + run: () => { + clusterStore.load(); + }, + runAfter: initUserStoreInjectable, + }; + }, injectionToken: beforeApplicationIsLoadingInjectionToken, }); diff --git a/packages/core/src/features/file-system-provisioner/main/init-store.injectable.ts b/packages/core/src/features/file-system-provisioner/main/init-store.injectable.ts index 33709e7ca4..9b60f420b5 100644 --- a/packages/core/src/features/file-system-provisioner/main/init-store.injectable.ts +++ b/packages/core/src/features/file-system-provisioner/main/init-store.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import fileSystemProvisionerStoreInjectable from "../../../extensions/extension-loader/file-system-provisioner-store/file-system-provisioner-store.injectable"; -import { onLoadOfApplicationInjectionToken } from "../../../main/start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const initFileSystemProvisionerStoreInjectable = getInjectable({ id: "init-file-system-provisioner-store", diff --git a/packages/core/src/features/hotbar/store/main/init.injectable.ts b/packages/core/src/features/hotbar/store/main/init.injectable.ts index 3ce13d7eb9..dc9ffa33a8 100644 --- a/packages/core/src/features/hotbar/store/main/init.injectable.ts +++ b/packages/core/src/features/hotbar/store/main/init.injectable.ts @@ -4,19 +4,21 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import hotbarStoreInjectable from "../../../../common/hotbars/store.injectable"; -import { onLoadOfApplicationInjectionToken } from "../../../../main/start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; import setupSyncingOfGeneralCatalogEntitiesInjectable from "../../../../main/start-main-application/runnables/setup-syncing-of-general-catalog-entities.injectable"; const initHotbarStoreInjectable = getInjectable({ id: "init-hotbar-store", - instantiate: (di) => ({ - run: () => { - const hotbarStore = di.inject(hotbarStoreInjectable); + instantiate: (di) => { + const hotbarStore = di.inject(hotbarStoreInjectable); - hotbarStore.load(); - }, - runAfter: setupSyncingOfGeneralCatalogEntitiesInjectable, - }), + return { + run: () => { + hotbarStore.load(); + }, + runAfter: setupSyncingOfGeneralCatalogEntitiesInjectable, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/features/shell-sync/main/setup-shell.injectable.ts b/packages/core/src/features/shell-sync/main/setup-shell.injectable.ts index 44e351a054..25b007a175 100644 --- a/packages/core/src/features/shell-sync/main/setup-shell.injectable.ts +++ b/packages/core/src/features/shell-sync/main/setup-shell.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import loggerInjectable from "../../../common/logger.injectable"; -import { onLoadOfApplicationInjectionToken } from "../../../main/start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; import isSnapPackageInjectable from "../../../common/vars/is-snap-package.injectable"; import electronAppInjectable from "../../../main/electron-app/electron-app.injectable"; import computeShellEnvironmentInjectable from "./compute-shell-environment.injectable"; @@ -15,56 +15,58 @@ import { unionPATHs } from "@k8slens/utilities"; const setupShellInjectable = getInjectable({ id: "setup-shell", - instantiate: (di) => ({ - run: async () => { - const logger = di.inject(loggerInjectable); - const isSnapPackage = di.inject(isSnapPackageInjectable); - const electronApp = di.inject(electronAppInjectable); - const resolvedUserShellSetting = di.inject(userShellSettingInjectable); - const computeShellEnvironment = di.inject(computeShellEnvironmentInjectable); - const emitShellSyncFailed = di.inject(emitShellSyncFailedInjectable); + instantiate: (di) => { + const logger = di.inject(loggerInjectable); + const isSnapPackage = di.inject(isSnapPackageInjectable); + const electronApp = di.inject(electronAppInjectable); + const resolvedUserShellSetting = di.inject(userShellSettingInjectable); + const computeShellEnvironment = di.inject(computeShellEnvironmentInjectable); + const emitShellSyncFailed = di.inject(emitShellSyncFailedInjectable); - logger.info("🐚 Syncing shell environment"); + return { + run: async (): Promise => { + logger.info("🐚 Syncing shell environment"); - const result = await computeShellEnvironment(resolvedUserShellSetting.get()); + const result = await computeShellEnvironment(resolvedUserShellSetting.get()); - if (!result.callWasSuccessful) { - logger.error(`[SHELL-SYNC]: ${result.error}`); - emitShellSyncFailed(result.error); + if (!result.callWasSuccessful) { + logger.error(`[SHELL-SYNC]: ${result.error}`); + emitShellSyncFailed(result.error); - return; - } + return; + } - const env = result.response; + const env = result.response; - if (!env) { - logger.debug("[SHELL-SYNC]: nothing to do, env not special in shells"); + if (!env) { + logger.debug("[SHELL-SYNC]: nothing to do, env not special in shells"); - return; - } + return; + } - if (!env.LANG) { - // the LANG env var expects an underscore instead of electron's dash - env.LANG = `${electronApp.getLocale().replace("-", "_")}.UTF-8`; - } else if (!env.LANG.endsWith(".UTF-8")) { - env.LANG += ".UTF-8"; - } + if (!env.LANG) { + // the LANG env var expects an underscore instead of electron's dash + env.LANG = `${electronApp.getLocale().replace("-", "_")}.UTF-8`; + } else if (!env.LANG.endsWith(".UTF-8")) { + env.LANG += ".UTF-8"; + } - if (!isSnapPackage) { - // Prefer the synced PATH over the initial one - process.env.PATH = unionPATHs(env.PATH ?? "", process.env.PATH ?? ""); - } + if (!isSnapPackage) { + // Prefer the synced PATH over the initial one + process.env.PATH = unionPATHs(env.PATH ?? "", process.env.PATH ?? ""); + } - // The spread operator allows joining of objects. The precedence is last to first. - process.env = { - ...env, - ...process.env, - }; + // The spread operator allows joining of objects. The precedence is last to first. + process.env = { + ...env, + ...process.env, + }; - logger.info(`[SHELL-SYNC]: Synced shell env`); - logger.debug(`[SHELL-SYNC]: updated env`, process.env); - }, - }), + logger.info(`[SHELL-SYNC]: Synced shell env`); + logger.debug(`[SHELL-SYNC]: updated env`, process.env); + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/features/theme/system-type/main/setup-update-emitter.injectable.ts b/packages/core/src/features/theme/system-type/main/setup-update-emitter.injectable.ts index 0125799531..09f2991f42 100644 --- a/packages/core/src/features/theme/system-type/main/setup-update-emitter.injectable.ts +++ b/packages/core/src/features/theme/system-type/main/setup-update-emitter.injectable.ts @@ -4,26 +4,28 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { reaction } from "mobx"; -import { onLoadOfApplicationInjectionToken } from "../../../../main/start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; import operatingSystemThemeInjectable from "../../../../main/theme/operating-system-theme.injectable"; import emitSystemThemeTypeUpdateInjectable from "./emit-update.injectable"; const setupSystemThemeTypeUpdaterEmitterInjectable = getInjectable({ id: "setup-system-theme-type-updater-emitter", - instantiate: (di) => ({ - run: () => { - const operatingSystemTheme = di.inject(operatingSystemThemeInjectable); - const emitSystemThemeTypeUpdate = di.inject(emitSystemThemeTypeUpdateInjectable); + instantiate: (di) => { + const operatingSystemTheme = di.inject(operatingSystemThemeInjectable); + const emitSystemThemeTypeUpdate = di.inject(emitSystemThemeTypeUpdateInjectable); - reaction( - () => operatingSystemTheme.get(), - emitSystemThemeTypeUpdate, - { - fireImmediately: true, - }, - ); - }, - }), + return { + run: () => { + reaction( + () => operatingSystemTheme.get(), + emitSystemThemeTypeUpdate, + { + fireImmediately: true, + }, + ); + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/app-paths/setup-app-paths.injectable.ts b/packages/core/src/main/app-paths/setup-app-paths.injectable.ts index 5f316014a4..34178547c3 100644 --- a/packages/core/src/main/app-paths/setup-app-paths.injectable.ts +++ b/packages/core/src/main/app-paths/setup-app-paths.injectable.ts @@ -13,7 +13,7 @@ import { fromPairs, map } from "lodash/fp"; import { pipeline } from "@ogre-tools/fp"; import joinPathsInjectable from "../../common/path/join-paths.injectable"; import appNameInjectable from "../../common/vars/app-name.injectable"; -import { appPathsRunnablePhaseInjectionToken } from "../start-main-application/runnable-tokens/phases"; +import { beforeAnythingInjectionToken } from "@k8slens/application-for-electron-main"; const setupAppPathsInjectable = getInjectable({ id: "setup-app-paths", @@ -48,7 +48,7 @@ const setupAppPathsInjectable = getInjectable({ }, }), - injectionToken: appPathsRunnablePhaseInjectionToken, + injectionToken: beforeAnythingInjectionToken, }); export default setupAppPathsInjectable; diff --git a/packages/core/src/main/cluster/initialize-manager.injectable.ts b/packages/core/src/main/cluster/initialize-manager.injectable.ts index 76cafb44a1..63a8dd7642 100644 --- a/packages/core/src/main/cluster/initialize-manager.injectable.ts +++ b/packages/core/src/main/cluster/initialize-manager.injectable.ts @@ -3,18 +3,20 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { onLoadOfApplicationInjectionToken } from "../start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; import clusterManagerInjectable from "./manager.injectable"; const initializeClusterManagerInjectable = getInjectable({ id: "initialize-cluster-manager", - instantiate: (di) => ({ - run: () => { - const clusterManager = di.inject(clusterManagerInjectable); + instantiate: (di) => { + const clusterManager = di.inject(clusterManagerInjectable); - clusterManager.init(); - }, - }), + return { + run: () => { + clusterManager.init(); + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, causesSideEffects: true, }); diff --git a/packages/core/src/main/create-app.ts b/packages/core/src/main/create-app.ts deleted file mode 100644 index 57f764706f..0000000000 --- a/packages/core/src/main/create-app.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * 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 { runInAction } from "mobx"; -import type { CreateApplication } from "../common/create-app"; -import nodeEnvInjectionToken from "../common/vars/node-env-injection-token"; -import { getDi } from "./getDi"; -import { registerInjectables } from "./register-injectables"; -import startMainApplicationInjectable from "./start-main-application/start-main-application.injectable"; - -export const createApplication: CreateApplication = (config) => { - const { mode } = config; - const di = getDi(); - - runInAction(() => { - di.register(getInjectable({ - id: "node-env", - instantiate: () => mode, - injectionToken: nodeEnvInjectionToken, - })); - - registerInjectables(di); - }); - - return { - start: di.inject(startMainApplicationInjectable), - di, - }; -}; diff --git a/packages/core/src/main/electron-app/features/wait-for-electron-to-be-ready.injectable.ts b/packages/core/src/main/electron-app/features/wait-for-electron-to-be-ready.injectable.ts deleted file mode 100644 index 586e8d7ac2..0000000000 --- a/packages/core/src/main/electron-app/features/wait-for-electron-to-be-ready.injectable.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * 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 electronAppInjectable from "../electron-app.injectable"; - -const waitForElectronToBeReadyInjectable = getInjectable({ - id: "wait-for-electron-to-be-ready", - - instantiate: (di) => () => di.inject(electronAppInjectable).whenReady(), -}); - -export default waitForElectronToBeReadyInjectable; diff --git a/packages/core/src/main/electron-app/runnables/enforce-single-application-instance.injectable.ts b/packages/core/src/main/electron-app/runnables/enforce-single-application-instance.injectable.ts index b310838cbe..e590f488d4 100644 --- a/packages/core/src/main/electron-app/runnables/enforce-single-application-instance.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/enforce-single-application-instance.injectable.ts @@ -3,25 +3,27 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { beforeElectronIsReadyInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; import requestSingleInstanceLockInjectable from "../features/request-single-instance-lock.injectable"; import exitAppInjectable from "../features/exit-app.injectable"; const enforceSingleApplicationInstanceInjectable = getInjectable({ id: "enforce-single-application-instance", - instantiate: (di) => ({ - run: () => { - const requestSingleInstanceLock = di.inject(requestSingleInstanceLockInjectable); - const exitApp = di.inject(exitAppInjectable); + instantiate: (di) => { + const requestSingleInstanceLock = di.inject(requestSingleInstanceLockInjectable); + const exitApp = di.inject(exitAppInjectable); - if (!requestSingleInstanceLock()) { - exitApp(); - } + return { + run: () => { + if (!requestSingleInstanceLock()) { + exitApp(); + } - return undefined; - }, - }), + return undefined; + }, + }; + }, injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/electron-app/runnables/setup-application-name.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-application-name.injectable.ts index ac67925125..3ae826e692 100644 --- a/packages/core/src/main/electron-app/runnables/setup-application-name.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-application-name.injectable.ts @@ -4,22 +4,22 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import appNameInjectable from "../../../common/vars/app-name.injectable"; -import { beforeElectronIsReadyInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; import electronAppInjectable from "../electron-app.injectable"; const setupApplicationNameInjectable = getInjectable({ id: "setup-application-name", - instantiate: (di) => ({ - run: () => { - const app = di.inject(electronAppInjectable); - const appName = di.inject(appNameInjectable); + instantiate: (di) => { + const app = di.inject(electronAppInjectable); + const appName = di.inject(appNameInjectable); - app.setName(appName); - - return undefined; - }, - }), + return { + run: () => { + app.setName(appName); + }, + }; + }, injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/electron-app/runnables/setup-deep-linking.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-deep-linking.injectable.ts index 979693b822..de3aaaae3b 100644 --- a/packages/core/src/main/electron-app/runnables/setup-deep-linking.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-deep-linking.injectable.ts @@ -7,63 +7,67 @@ import electronAppInjectable from "../electron-app.injectable"; import openDeepLinkInjectable from "../../protocol-handler/lens-protocol-router-main/open-deep-link-for-url/open-deep-link.injectable"; import loggerInjectable from "../../../common/logger.injectable"; import commandLineArgumentsInjectable from "../../utils/command-line-arguments.injectable"; -import { startsWith, toLower } from "lodash/fp"; -import { onLoadOfApplicationInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { pipeline } from "@ogre-tools/fp"; +import { find, startsWith, toLower, map } from "lodash/fp"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; import showApplicationWindowInjectable from "../../start-main-application/lens-window/show-application-window.injectable"; const setupDeepLinkingInjectable = getInjectable({ id: "setup-deep-linking", - instantiate: (di) => ({ - run: async () => { - const app = di.inject(electronAppInjectable); - const logger = di.inject(loggerInjectable); - const openDeepLinkForUrl = di.inject(openDeepLinkInjectable); - const showApplicationWindow = di.inject(showApplicationWindowInjectable); - const firstInstanceCommandLineArguments = di.inject(commandLineArgumentsInjectable); + instantiate: (di) => { + const app = di.inject(electronAppInjectable); + const logger = di.inject(loggerInjectable); + const openDeepLinkForUrl = di.inject(openDeepLinkInjectable); + const showApplicationWindow = di.inject(showApplicationWindowInjectable); - logger.info(`📟 Setting protocol client for lens://`); + const firstInstanceCommandLineArguments = di.inject( + commandLineArgumentsInjectable, + ); - if (app.setAsDefaultProtocolClient("lens")) { - logger.info("📟 Protocol client register succeeded ✅"); - } else { - logger.info("📟 Protocol client register failed ❗"); - } + return { + run: async () => { + logger.info(`📟 Setting protocol client for lens://`); - const url = getDeepLinkUrl(firstInstanceCommandLineArguments); + if (app.setAsDefaultProtocolClient("lens")) { + logger.info("📟 Protocol client register succeeded ✅"); + } else { + logger.info("📟 Protocol client register failed ❗"); + } - if (url) { - await openDeepLinkForUrl(url); - } + const url = getDeepLinkUrl(firstInstanceCommandLineArguments); - app.on("open-url", async (event, url) => { - event.preventDefault(); + if (url) { + await openDeepLinkForUrl(url); + } - await openDeepLinkForUrl(url); - }); + app.on("open-url", async (event, url) => { + event.preventDefault(); - app.on( - "second-instance", - async (_, secondInstanceCommandLineArguments) => { - const url = getDeepLinkUrl(secondInstanceCommandLineArguments); + await openDeepLinkForUrl(url); + }); - await showApplicationWindow(); + app.on( + "second-instance", - if (url) { - await openDeepLinkForUrl(url); - } - }, - ); - }, - }), + async (_, secondInstanceCommandLineArguments) => { + const url = getDeepLinkUrl(secondInstanceCommandLineArguments); + + await showApplicationWindow(); + + if (url) { + await openDeepLinkForUrl(url); + } + }, + ); + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); export default setupDeepLinkingInjectable; -const getDeepLinkUrl = (commandLineArguments: string[]) => ( - commandLineArguments - .map(toLower) - .find(startsWith("lens://")) -); +const getDeepLinkUrl = (commandLineArguments: string[]) => + pipeline(commandLineArguments, map(toLower), find(startsWith("lens://"))); diff --git a/packages/core/src/main/electron-app/runnables/setup-developer-tools-in-development-environment.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-developer-tools-in-development-environment.injectable.ts index 22fe933748..2dbf86c534 100644 --- a/packages/core/src/main/electron-app/runnables/setup-developer-tools-in-development-environment.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-developer-tools-in-development-environment.injectable.ts @@ -3,40 +3,42 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import nodeEnvInjectionToken from "../../../common/vars/node-env-injection-token"; +import { nodeEnvInjectionToken } from "../../../common/vars/node-env-injection-token"; import loggerInjectable from "../../../common/logger.injectable"; -import { onLoadOfApplicationInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const setupDeveloperToolsInDevelopmentEnvironmentInjectable = getInjectable({ id: "setup-developer-tools-in-development-environment", - instantiate: (di) => ({ - run: () => { - const logger = di.inject(loggerInjectable); - const nodeEnv = di.inject(nodeEnvInjectionToken); + instantiate: (di) => { + const logger = di.inject(loggerInjectable); + const nodeEnv = di.inject(nodeEnvInjectionToken); - if (nodeEnv !== "development") { - return; - } - - logger.info("🤓 Installing developer tools"); - - void (async () => { - try { - const { - default: devToolsInstaller, - REACT_DEVELOPER_TOOLS, - } = await import("electron-devtools-installer"); - - const name = await devToolsInstaller([REACT_DEVELOPER_TOOLS]); - - logger.info(`[DEVTOOLS-INSTALLER]: installed ${name}`); - } catch (error) { - logger.error(`[DEVTOOLS-INSTALLER]: failed`, { error }); + return { + run: () => { + if (nodeEnv !== "development") { + return; } - })(); - }, - }), + + logger.info("🤓 Installing developer tools"); + + void (async () => { + try { + const { + default: devToolsInstaller, + REACT_DEVELOPER_TOOLS, + } = await import("electron-devtools-installer"); + + const name = await devToolsInstaller([REACT_DEVELOPER_TOOLS]); + + logger.info(`[DEVTOOLS-INSTALLER]: installed ${name}`); + } catch (error) { + logger.error(`[DEVTOOLS-INSTALLER]: failed`, { error }); + } + })(); + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/electron-app/runnables/setup-device-shutdown.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-device-shutdown.injectable.ts index a8502d3738..43aab5006e 100644 --- a/packages/core/src/main/electron-app/runnables/setup-device-shutdown.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-device-shutdown.injectable.ts @@ -5,19 +5,21 @@ import { getInjectable } from "@ogre-tools/injectable"; import powerMonitorInjectable from "../features/power-monitor.injectable"; import exitAppInjectable from "../features/exit-app.injectable"; -import { onLoadOfApplicationInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const setupDeviceShutdownInjectable = getInjectable({ id: "setup-device-shutdown", - instantiate: (di) => ({ - run: () => { - const powerMonitor = di.inject(powerMonitorInjectable); - const exitApp = di.inject(exitAppInjectable); + instantiate: (di) => { + const powerMonitor = di.inject(powerMonitorInjectable); + const exitApp = di.inject(exitAppInjectable); - powerMonitor.on("shutdown", exitApp); - }, - }), + return { + run: () => { + powerMonitor.on("shutdown", exitApp); + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable.ts index 0781ee04c3..b5f4bd289f 100644 --- a/packages/core/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable.ts @@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { setupIpcMainHandlers } from "./setup-ipc-main-handlers"; import loggerInjectable from "../../../../common/logger.injectable"; import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable"; -import { onLoadOfApplicationInjectionToken } from "../../../start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; import applicationMenuItemCompositeInjectable from "../../../../features/application-menu/main/application-menu-item-composite.injectable"; import emitAppEventInjectable from "../../../../common/app-event-bus/emit-event.injectable"; import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable"; @@ -15,26 +15,28 @@ import pushCatalogToRendererInjectable from "../../../catalog-sync-to-renderer/p const setupIpcMainHandlersInjectable = getInjectable({ id: "setup-ipc-main-handlers", - instantiate: (di) => ({ - run: () => { - const logger = di.inject(loggerInjectable); - const applicationMenuItemComposite = di.inject(applicationMenuItemCompositeInjectable); - const pushCatalogToRenderer = di.inject(pushCatalogToRendererInjectable); - const clusterStore = di.inject(clusterStoreInjectable); - const emitAppEvent = di.inject(emitAppEventInjectable); - const getClusterById = di.inject(getClusterByIdInjectable); + instantiate: (di) => { + const logger = di.inject(loggerInjectable); + const applicationMenuItemComposite = di.inject(applicationMenuItemCompositeInjectable); + const pushCatalogToRenderer = di.inject(pushCatalogToRendererInjectable); + const clusterStore = di.inject(clusterStoreInjectable); + const emitAppEvent = di.inject(emitAppEventInjectable); + const getClusterById = di.inject(getClusterByIdInjectable); - logger.debug("[APP-MAIN] initializing ipc main handlers"); + return { + run: () => { + logger.debug("[APP-MAIN] initializing ipc main handlers"); - setupIpcMainHandlers({ - applicationMenuItemComposite, - pushCatalogToRenderer, - clusterStore, - emitAppEvent, - getClusterById, - }); - }, - }), + setupIpcMainHandlers({ + applicationMenuItemComposite, + pushCatalogToRenderer, + clusterStore, + emitAppEvent, + getClusterById, + }); + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, causesSideEffects: true, diff --git a/packages/core/src/main/electron-app/runnables/setup-main-window-visibility-after-activation.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-main-window-visibility-after-activation.injectable.ts index 90ca7c73cb..78b4a2d3ec 100644 --- a/packages/core/src/main/electron-app/runnables/setup-main-window-visibility-after-activation.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-main-window-visibility-after-activation.injectable.ts @@ -5,27 +5,29 @@ import { getInjectable } from "@ogre-tools/injectable"; import electronAppInjectable from "../electron-app.injectable"; import loggerInjectable from "../../../common/logger.injectable"; -import { onLoadOfApplicationInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; import showApplicationWindowInjectable from "../../start-main-application/lens-window/show-application-window.injectable"; const setupMainWindowVisibilityAfterActivationInjectable = getInjectable({ id: "setup-main-window-visibility-after-activation", - instantiate: (di) => ({ - run: () => { - const app = di.inject(electronAppInjectable); - const showApplicationWindow = di.inject(showApplicationWindowInjectable); - const logger = di.inject(loggerInjectable); + instantiate: (di) => { + const app = di.inject(electronAppInjectable); + const showApplicationWindow = di.inject(showApplicationWindowInjectable); + const logger = di.inject(loggerInjectable); - app.on("activate", (_, windowIsVisible) => { - logger.info("APP:ACTIVATE", { hasVisibleWindows: windowIsVisible }); + return { + run: () => { + app.on("activate", (_, windowIsVisible) => { + logger.info("APP:ACTIVATE", { hasVisibleWindows: windowIsVisible }); - if (!windowIsVisible) { - void showApplicationWindow(); - } - }); - }, - }), + if (!windowIsVisible) { + void showApplicationWindow(); + } + }); + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/electron-app/runnables/setup-runnables-after-window-is-opened.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-runnables-after-window-is-opened.injectable.ts index a56e337e01..705a6c4a55 100644 --- a/packages/core/src/main/electron-app/runnables/setup-runnables-after-window-is-opened.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-runnables-after-window-is-opened.injectable.ts @@ -3,25 +3,26 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { beforeElectronIsReadyInjectionToken, afterWindowIsOpenedInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; +import { afterWindowIsOpenedInjectionToken } from "../../start-main-application/runnable-tokens/phases"; import electronAppInjectable from "../electron-app.injectable"; import { runManyFor } from "@k8slens/run-many"; const setupRunnablesAfterWindowIsOpenedInjectable = getInjectable({ id: "setup-runnables-after-window-is-opened", - instantiate: (di) => ({ - run: () => { - const afterWindowIsOpened = runManyFor(di)(afterWindowIsOpenedInjectionToken); - const app = di.inject(electronAppInjectable); + instantiate: (di) => { + const afterWindowIsOpened = runManyFor(di)(afterWindowIsOpenedInjectionToken); + const app = di.inject(electronAppInjectable); - app.on("browser-window-created", () => { - afterWindowIsOpened(); - }); - - return undefined; - }, - }), + return { + run: () => { + app.on("browser-window-created", () => { + afterWindowIsOpened(); + }); + }, + }; + }, injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/electron-app/runnables/setup-runnables-before-closing-of-application.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-runnables-before-closing-of-application.injectable.ts index 6c72fced32..15aa920b5b 100644 --- a/packages/core/src/main/electron-app/runnables/setup-runnables-before-closing-of-application.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-runnables-before-closing-of-application.injectable.ts @@ -3,7 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { beforeElectronIsReadyInjectionToken, beforeQuitOfFrontEndInjectionToken, beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; +import { beforeQuitOfFrontEndInjectionToken, beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/phases"; import electronAppInjectable from "../electron-app.injectable"; import isIntegrationTestingInjectable from "../../../common/vars/is-integration-testing.injectable"; import autoUpdaterInjectable from "../features/auto-updater.injectable"; @@ -12,36 +13,37 @@ import { runManySyncFor } from "@k8slens/run-many"; const setupRunnablesBeforeClosingOfApplicationInjectable = getInjectable({ id: "setup-closing-of-application", - instantiate: (di) => ({ - run: () => { - const runManySync = runManySyncFor(di); - const runRunnablesBeforeQuitOfFrontEnd = runManySync(beforeQuitOfFrontEndInjectionToken); - const runRunnablesBeforeQuitOfBackEnd = runManySync(beforeQuitOfBackEndInjectionToken); - const app = di.inject(electronAppInjectable); - const isIntegrationTesting = di.inject(isIntegrationTestingInjectable); - const autoUpdater = di.inject(autoUpdaterInjectable); - let isAutoUpdating = false; + instantiate: (di) => { + const runManySync = runManySyncFor(di); + const runRunnablesBeforeQuitOfFrontEnd = runManySync(beforeQuitOfFrontEndInjectionToken); + const runRunnablesBeforeQuitOfBackEnd = runManySync(beforeQuitOfBackEndInjectionToken); + const app = di.inject(electronAppInjectable); + const isIntegrationTesting = di.inject(isIntegrationTestingInjectable); + const autoUpdater = di.inject(autoUpdaterInjectable); - autoUpdater.on("before-quit-for-update", () => { - isAutoUpdating = true; - }); + return { + run: () => { + let isAutoUpdating = false; - app.on("will-quit", (event) => { - runRunnablesBeforeQuitOfFrontEnd(); + autoUpdater.on("before-quit-for-update", () => { + isAutoUpdating = true; + }); - const shouldQuitBackEnd = isIntegrationTesting || isAutoUpdating; + app.on("will-quit", (event) => { + runRunnablesBeforeQuitOfFrontEnd(); - if (shouldQuitBackEnd) { - runRunnablesBeforeQuitOfBackEnd(); - } else { - // IMPORTANT: This cannot be destructured as it would break binding of "this" for the Electron event - event.preventDefault(); - } - }); + const shouldQuitBackEnd = isIntegrationTesting || isAutoUpdating; - return undefined; - }, - }), + if (shouldQuitBackEnd) { + runRunnablesBeforeQuitOfBackEnd(); + } else { + // IMPORTANT: This cannot be destructured as it would break binding of "this" for the Electron event + event.preventDefault(); + } + }); + }, + }; + }, injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/getDi.ts b/packages/core/src/main/getDi.ts deleted file mode 100644 index 8d4b1ff57f..0000000000 --- a/packages/core/src/main/getDi.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { createContainer } from "@ogre-tools/injectable"; -import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; -import { setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; - -export const getDi = () => { - const environment = "main"; - const di = createContainer(environment); - - registerMobX(di); - setLegacyGlobalDiForExtensionApi(di, environment); - - return di; -}; diff --git a/packages/core/src/main/getDiForUnitTesting.ts b/packages/core/src/main/getDiForUnitTesting.ts index c40548261d..cc70cef88a 100644 --- a/packages/core/src/main/getDiForUnitTesting.ts +++ b/packages/core/src/main/getDiForUnitTesting.ts @@ -5,7 +5,7 @@ import { chunk } from "lodash/fp"; import type { DiContainer } from "@ogre-tools/injectable"; -import { isInjectable } from "@ogre-tools/injectable"; +import { createContainer, isInjectable } from "@ogre-tools/injectable"; import spawnInjectable from "./child-process/spawn.injectable"; import initializeExtensionsInjectable from "./start-main-application/runnables/initialize-extensions.injectable"; import setupIpcMainHandlersInjectable from "./electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable"; @@ -28,14 +28,20 @@ import electronInjectable from "./utils/resolve-system-proxy/electron.injectable import initializeClusterManagerInjectable from "./cluster/initialize-manager.injectable"; import type { GlobalOverride } from "@k8slens/test-utils"; import { getOverrideFsWithFakes } from "../test-utils/override-fs-with-fakes"; -import { getDi } from "./getDi"; +import { + setLegacyGlobalDiForExtensionApi, +} from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; +import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) { const { doGeneralOverrides = false, } = opts; - const di = getDi(); + const di = createContainer("main"); + + registerMobX(di); + setLegacyGlobalDiForExtensionApi(di, "main"); di.preventSideEffects(); diff --git a/packages/core/src/main/library.ts b/packages/core/src/main/library.ts index ab5d681935..cb396cf448 100644 --- a/packages/core/src/main/library.ts +++ b/packages/core/src/main/library.ts @@ -4,14 +4,12 @@ */ // @experimental -export { - afterApplicationIsLoadedInjectionToken, - beforeApplicationIsLoadingInjectionToken, - beforeElectronIsReadyInjectionToken, - onLoadOfApplicationInjectionToken, -} from "./start-main-application/runnable-tokens/phases"; -export { createApplication } from "./create-app"; -export type { CreateApplication, Application, ApplicationConfig } from "../common/create-app"; +export type { + Environments, +} from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; + +export { registerLensCore } from "./register-lens-core"; +export { nodeEnvInjectionToken } from "../common/vars/node-env-injection-token"; export * as Mobx from "mobx"; export * as mainExtensionApi from "../extensions/main-api"; export * as commonExtensionApi from "../extensions/common-api"; diff --git a/packages/core/src/renderer/register-injectables.ts b/packages/core/src/main/register-lens-core.ts similarity index 66% rename from packages/core/src/renderer/register-injectables.ts rename to packages/core/src/main/register-lens-core.ts index 0974a1a08b..cf69b6e575 100644 --- a/packages/core/src/renderer/register-injectables.ts +++ b/packages/core/src/main/register-lens-core.ts @@ -2,20 +2,26 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ - import type { DiContainer } from "@ogre-tools/injectable"; import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; import { runInAction } from "mobx"; +import type { + Environments } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; +import { + setLegacyGlobalDiForExtensionApi, +} from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; + +export function registerLensCore(di: DiContainer, environment: Environments) { + setLegacyGlobalDiForExtensionApi(di, environment); -export function registerInjectables(di: DiContainer) { runInAction(() => { autoRegister({ di, targetModule: module, getRequireContexts: () => [ require.context("./", true, CONTEXT_MATCHER_FOR_NON_FEATURES), - require.context("../common", true, CONTEXT_MATCHER_FOR_NON_FEATURES), require.context("../extensions", true, CONTEXT_MATCHER_FOR_NON_FEATURES), + require.context("../common", true, CONTEXT_MATCHER_FOR_NON_FEATURES), require.context("../features", true, CONTEXT_MATCHER_FOR_FEATURES), ], }); diff --git a/packages/core/src/main/start-main-application/runnable-tokens/phases.ts b/packages/core/src/main/start-main-application/runnable-tokens/phases.ts deleted file mode 100644 index 26e2b62da1..0000000000 --- a/packages/core/src/main/start-main-application/runnable-tokens/phases.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * 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 { Runnable, RunnableSync } from "@k8slens/run-many"; - -/** - * These tokens are here so that the importing of their respective dependencies - * can be delayed until all of them are ready - */ - -/** - * This runnable token should only have the app paths init so that it can be run by itself - */ -export const appPathsRunnablePhaseInjectionToken = getInjectionToken({ - id: "app-paths-runnable-phase", -}); - -export const showLoadingRunnablePhaseInjectionToken = getInjectionToken({ - id: "show-loading-runnable-phase", -}); - -export const showInitialWindowRunnablePhaseInjectionToken = getInjectionToken({ - id: "show-initial-window-runnable-phase", -}); - -export const onLoadOfApplicationInjectionToken = getInjectionToken({ - id: "on-load-of-application", -}); - -export const beforeQuitOfFrontEndInjectionToken = getInjectionToken({ - id: "before-quit-of-front-end", -}); - -export const beforeQuitOfBackEndInjectionToken = getInjectionToken({ - id: "before-quit-of-back-end", -}); - -export const beforeElectronIsReadyInjectionToken = getInjectionToken({ - id: "before-electron-is-ready", -}); - -export const beforeApplicationIsLoadingInjectionToken = getInjectionToken({ - id: "before-application-is-loading", -}); - -export const afterWindowIsOpenedInjectionToken = getInjectionToken({ - id: "after-window-is-opened", -}); - -export const afterRootFrameIsReadyInjectionToken = getInjectionToken({ - id: "after-root-frame-is-ready", -}); - -export const afterApplicationIsLoadedInjectionToken = getInjectionToken({ - id: "after-application-is-loaded", -}); diff --git a/packages/core/src/main/start-main-application/runnables/emit-service-start-to-event-bus.injectable.ts b/packages/core/src/main/start-main-application/runnables/emit-service-start-to-event-bus.injectable.ts index 8d9e8a1a38..d547ae3b14 100644 --- a/packages/core/src/main/start-main-application/runnables/emit-service-start-to-event-bus.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/emit-service-start-to-event-bus.injectable.ts @@ -4,18 +4,20 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import emitAppEventInjectable from "../../../common/app-event-bus/emit-event.injectable"; -import { afterApplicationIsLoadedInjectionToken } from "../runnable-tokens/phases"; +import { afterApplicationIsLoadedInjectionToken } from "@k8slens/application"; const emitServiceStartToEventBusInjectable = getInjectable({ id: "emit-service-start-to-event-bus", - instantiate: (di) => ({ - run: () => { - const emitAppEvent = di.inject(emitAppEventInjectable); + instantiate: (di) => { + const emitAppEvent = di.inject(emitAppEventInjectable); - emitAppEvent({ name: "service", action: "start" }); - }, - }), + return { + run: () => { + emitAppEvent({ name: "service", action: "start" }); + }, + }; + }, injectionToken: afterApplicationIsLoadedInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/initialize-extensions.injectable.ts b/packages/core/src/main/start-main-application/runnables/initialize-extensions.injectable.ts index 14ef494e02..8f12e9b905 100644 --- a/packages/core/src/main/start-main-application/runnables/initialize-extensions.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/initialize-extensions.injectable.ts @@ -9,51 +9,55 @@ import loggerInjectable from "../../../common/logger.injectable"; import extensionDiscoveryInjectable from "../../../extensions/extension-discovery/extension-discovery.injectable"; import extensionLoaderInjectable from "../../../extensions/extension-loader/extension-loader.injectable"; import showErrorPopupInjectable from "../../electron-app/features/show-error-popup.injectable"; -import { onLoadOfApplicationInjectionToken } from "../runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const initializeExtensionsInjectable = getInjectable({ id: "initialize-extensions", - instantiate: (di) => ({ - run: async () => { - const logger = di.inject(loggerInjectable); - const extensionDiscovery = di.inject(extensionDiscoveryInjectable); - const extensionLoader = di.inject(extensionLoaderInjectable); - const showErrorPopup = di.inject(showErrorPopupInjectable); + instantiate: (di) => { + const logger = di.inject(loggerInjectable); + const extensionDiscovery = di.inject(extensionDiscoveryInjectable); + const extensionLoader = di.inject(extensionLoaderInjectable); + const showErrorPopup = di.inject(showErrorPopupInjectable); - logger.info("🧩 Initializing extensions"); + return { + run: async () => { + logger.info("🧩 Initializing extensions"); - await extensionDiscovery.init(); + await extensionDiscovery.init(); - await extensionLoader.init(); + await extensionLoader.init(); - try { - const extensions = await extensionDiscovery.load(); + try { + const extensions = await extensionDiscovery.load(); - // Start watching after bundled extensions are loaded - extensionDiscovery.watchExtensions(); + // Start watching after bundled extensions are loaded + extensionDiscovery.watchExtensions(); - // Subscribe to extensions that are copied or deleted to/from the extensions folder - extensionDiscovery.events - .on("add", (extension: InstalledExtension) => { - extensionLoader.addExtension(extension); - }) - .on("remove", (lensExtensionId: LensExtensionId) => { - extensionLoader.removeExtension(lensExtensionId); - }); + // Subscribe to extensions that are copied or deleted to/from the extensions folder + extensionDiscovery.events + .on("add", (extension: InstalledExtension) => { + extensionLoader.addExtension(extension); + }) + .on("remove", (lensExtensionId: LensExtensionId) => { + extensionLoader.removeExtension(lensExtensionId); + }); - extensionLoader.initExtensions(extensions); - } catch (error: any) { - showErrorPopup( - "Lens Error", - `Could not load extensions${error?.message ? `: ${error.message}` : ""}`, - ); + extensionLoader.initExtensions(extensions); + } catch (error: any) { + showErrorPopup( + "Lens Error", + `Could not load extensions${ + error?.message ? `: ${error.message}` : "" + }`, + ); - console.error(error); - console.trace(); - } - }, - }), + console.error(error); + console.trace(); + } + }, + }; + }, causesSideEffects: true, diff --git a/packages/core/src/main/start-main-application/runnables/kube-config-sync/add-source.injectable.ts b/packages/core/src/main/start-main-application/runnables/kube-config-sync/add-source.injectable.ts index a9117e840d..84f64a9be1 100644 --- a/packages/core/src/main/start-main-application/runnables/kube-config-sync/add-source.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/kube-config-sync/add-source.injectable.ts @@ -5,18 +5,20 @@ import { getInjectable } from "@ogre-tools/injectable"; import kubeconfigSyncManagerInjectable from "../../../catalog-sources/kubeconfig-sync/manager.injectable"; import catalogEntityRegistryInjectable from "../../../catalog/entity-registry.injectable"; -import { afterApplicationIsLoadedInjectionToken } from "../../runnable-tokens/phases"; +import { afterApplicationIsLoadedInjectionToken } from "@k8slens/application"; const addKubeconfigSyncAsEntitySourceInjectable = getInjectable({ id: "add-kubeconfig-sync-as-entity-source", - instantiate: (di) => ({ - run: () => { - const kubeConfigSyncManager = di.inject(kubeconfigSyncManagerInjectable); - const entityRegistry = di.inject(catalogEntityRegistryInjectable); + instantiate: (di) => { + const kubeConfigSyncManager = di.inject(kubeconfigSyncManagerInjectable); + const entityRegistry = di.inject(catalogEntityRegistryInjectable); - entityRegistry.addComputedSource("kubeconfig-sync", kubeConfigSyncManager.source); - }, - }), + return { + run: () => { + entityRegistry.addComputedSource("kubeconfig-sync", kubeConfigSyncManager.source); + }, + }; + }, injectionToken: afterApplicationIsLoadedInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/kube-config-sync/start-kube-config-sync.injectable.ts b/packages/core/src/main/start-main-application/runnables/kube-config-sync/start-kube-config-sync.injectable.ts index f1f5c34510..6c7384abe7 100644 --- a/packages/core/src/main/start-main-application/runnables/kube-config-sync/start-kube-config-sync.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/kube-config-sync/start-kube-config-sync.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { afterApplicationIsLoadedInjectionToken } from "../../runnable-tokens/phases"; +import { afterApplicationIsLoadedInjectionToken } from "@k8slens/application"; import directoryForKubeConfigsInjectable from "../../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import ensureDirInjectable from "../../../../common/fs/ensure-dir.injectable"; import kubeconfigSyncManagerInjectable from "../../../catalog-sources/kubeconfig-sync/manager.injectable"; @@ -12,18 +12,20 @@ import addKubeconfigSyncAsEntitySourceInjectable from "./add-source.injectable"; const startKubeConfigSyncInjectable = getInjectable({ id: "start-kubeconfig-sync", - instantiate: (di) => ({ - run: async () => { - const directoryForKubeConfigs = di.inject(directoryForKubeConfigsInjectable); - const kubeConfigSyncManager = di.inject(kubeconfigSyncManagerInjectable); - const ensureDir = di.inject(ensureDirInjectable); + instantiate: (di) => { + const directoryForKubeConfigs = di.inject(directoryForKubeConfigsInjectable); + const kubeConfigSyncManager = di.inject(kubeconfigSyncManagerInjectable); + const ensureDir = di.inject(ensureDirInjectable); - await ensureDir(directoryForKubeConfigs); + return { + run: async () => { + await ensureDir(directoryForKubeConfigs); - kubeConfigSyncManager.startSync(); - }, - runAfter: addKubeconfigSyncAsEntitySourceInjectable, - }), + kubeConfigSyncManager.startSync(); + }, + runAfter: addKubeconfigSyncAsEntitySourceInjectable, + }; + }, injectionToken: afterApplicationIsLoadedInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/sentry/setup.injectable.ts b/packages/core/src/main/start-main-application/runnables/sentry/setup.injectable.ts index 54504caa68..a2042a0200 100644 --- a/packages/core/src/main/start-main-application/runnables/sentry/setup.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/sentry/setup.injectable.ts @@ -3,22 +3,22 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { beforeElectronIsReadyInjectionToken } from "../../runnable-tokens/phases"; +import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; import initializeSentryReportingWithInjectable from "../../../../common/error-reporting/initialize-sentry-reporting.injectable"; import initializeSentryOnMainInjectable from "./initialize-on-main.injectable"; const setupSentryInjectable = getInjectable({ id: "setup-sentry", - instantiate: (di) => ({ - run: () => { - const initializeSentryReportingWith = di.inject(initializeSentryReportingWithInjectable); - const initializeSentryOnMain = di.inject(initializeSentryOnMainInjectable); + instantiate: (di) => { + const initializeSentryReportingWith = di.inject(initializeSentryReportingWithInjectable); + const initializeSentryOnMain = di.inject(initializeSentryOnMainInjectable); - initializeSentryReportingWith(initializeSentryOnMain); - - return undefined; - }, - }), + return { + run: () => { + initializeSentryReportingWith(initializeSentryOnMain); + } + }; + }, injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/setup-hardware-acceleration.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-hardware-acceleration.injectable.ts index f78c9fc4f6..0121d28f11 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-hardware-acceleration.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-hardware-acceleration.injectable.ts @@ -5,23 +5,23 @@ import { getInjectable } from "@ogre-tools/injectable"; import disableHardwareAccelerationInjectable from "../../electron-app/features/disable-hardware-acceleration.injectable"; import hardwareAccelerationShouldBeDisabledInjectable from "../../vars/hardware-acceleration-should-be-disabled.injectable"; -import { beforeElectronIsReadyInjectionToken } from "../runnable-tokens/phases"; +import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; const setupHardwareAccelerationInjectable = getInjectable({ id: "setup-hardware-acceleration", - instantiate: (di) => ({ - run: () => { - const hardwareAccelerationShouldBeDisabled = di.inject(hardwareAccelerationShouldBeDisabledInjectable); - const disableHardwareAcceleration = di.inject(disableHardwareAccelerationInjectable); + instantiate: (di) => { + const hardwareAccelerationShouldBeDisabled = di.inject(hardwareAccelerationShouldBeDisabledInjectable); + const disableHardwareAcceleration = di.inject(disableHardwareAccelerationInjectable); - if (hardwareAccelerationShouldBeDisabled) { - disableHardwareAcceleration(); - } - - return undefined; - }, - }), + return { + run: () => { + if (hardwareAccelerationShouldBeDisabled) { + disableHardwareAcceleration(); + } + }, + }; + }, injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/setup-hostnames.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-hostnames.injectable.ts index 312baa19fb..8aec456cff 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-hostnames.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-hostnames.injectable.ts @@ -4,24 +4,24 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import electronAppInjectable from "../../electron-app/electron-app.injectable"; -import { beforeElectronIsReadyInjectionToken } from "../runnable-tokens/phases"; +import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; const setupHostnamesInjectable = getInjectable({ id: "setup-hostnames", - instantiate: (di) => ({ - run: () => { - const app = di.inject(electronAppInjectable); + instantiate: (di) => { + const app = di.inject(electronAppInjectable); - app.commandLine.appendSwitch("host-rules", [ - "MAP localhost 127.0.0.1", - "MAP lens.app 127.0.0.1", - "MAP *.lens.app 127.0.0.1", - ].join()); - - return undefined; - }, - }), + return { + run: () => { + app.commandLine.appendSwitch("host-rules", [ + "MAP localhost 127.0.0.1", + "MAP lens.app 127.0.0.1", + "MAP *.lens.app 127.0.0.1", + ].join()); + }, + }; + }, injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/setup-immer.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-immer.injectable.ts index fb36d3f491..cec7aa6206 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-immer.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-immer.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { setAutoFreeze, enableMapSet } from "immer"; -import { beforeElectronIsReadyInjectionToken } from "../runnable-tokens/phases"; +import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; const setupImmerInjectable = getInjectable({ id: "setup-immer", @@ -15,8 +15,6 @@ const setupImmerInjectable = getInjectable({ // Required in `utils/storage-helper.ts` setAutoFreeze(false); // allow to merge mobx observables enableMapSet(); // allow to merge maps and sets - - return undefined; }, }), diff --git a/packages/core/src/main/start-main-application/runnables/setup-lens-proxy-certificate.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-lens-proxy-certificate.injectable.ts index 33bec82906..e02568e518 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-lens-proxy-certificate.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-lens-proxy-certificate.injectable.ts @@ -5,44 +5,44 @@ import { getInjectable } from "@ogre-tools/injectable"; import { generate } from "selfsigned"; import lensProxyCertificateInjectable from "../../../common/certificate/lens-proxy-certificate.injectable"; -import { beforeElectronIsReadyInjectionToken } from "../runnable-tokens/phases"; +import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; const setupLensProxyCertificateInjectable = getInjectable({ id: "setup-lens-proxy-certificate", - instantiate: (di) => ({ - run: () => { - const lensProxyCertificate = di.inject(lensProxyCertificateInjectable); + instantiate: (di) => { + const lensProxyCertificate = di.inject(lensProxyCertificateInjectable); - const cert = generate([ - { name: "commonName", value: "Lens Certificate Authority" }, - { name: "organizationName", value: "Lens" }, - ], { - keySize: 2048, - algorithm: "sha256", - days: 365, - extensions: [ - { - name: "basicConstraints", - cA: true, - }, - { - name: "subjectAltName", - altNames: [ - { type: 2, value: "*.lens.app" }, - { type: 2, value: "lens.app" }, - { type: 2, value: "localhost" }, - { type: 7, ip: "127.0.0.1" }, - ], - }, - ], - }); + return { + run: () => { + const cert = generate([ + { name: "commonName", value: "Lens Certificate Authority" }, + { name: "organizationName", value: "Lens" }, + ], { + keySize: 2048, + algorithm: "sha256", + days: 365, + extensions: [ + { + name: "basicConstraints", + cA: true, + }, + { + name: "subjectAltName", + altNames: [ + { type: 2, value: "*.lens.app" }, + { type: 2, value: "lens.app" }, + { type: 2, value: "localhost" }, + { type: 7, ip: "127.0.0.1" }, + ], + }, + ], + }); - lensProxyCertificate.set(cert); - - return undefined; - }, - }), + lensProxyCertificate.set(cert); + }, + }; + }, injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts index 9aa384b308..ebd3840a6c 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts @@ -9,7 +9,7 @@ import loggerInjectable from "../../../common/logger.injectable"; import lensProxyPortInjectable from "../../lens-proxy/lens-proxy-port.injectable"; import isWindowsInjectable from "../../../common/vars/is-windows.injectable"; import showErrorPopupInjectable from "../../electron-app/features/show-error-popup.injectable"; -import { beforeApplicationIsLoadingInjectionToken } from "../runnable-tokens/phases"; +import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application"; import buildVersionInjectable from "../../vars/build-version/build-version.injectable"; import initializeBuildVersionInjectable from "../../vars/build-version/init.injectable"; import lensProxyCertificateInjectable from "../../../common/certificate/lens-proxy-certificate.injectable"; @@ -19,65 +19,67 @@ import { Agent } from "https"; const setupLensProxyInjectable = getInjectable({ id: "setup-lens-proxy", - instantiate: (di) => ({ - run: async () => { - const lensProxy = di.inject(lensProxyInjectable); - const exitApp = di.inject(exitAppInjectable); - const logger = di.inject(loggerInjectable); - const lensProxyPort = di.inject(lensProxyPortInjectable); - const isWindows = di.inject(isWindowsInjectable); - const showErrorPopup = di.inject(showErrorPopupInjectable); - const buildVersion = di.inject(buildVersionInjectable); - const lensProxyCertificate = di.inject(lensProxyCertificateInjectable); - const fetch = di.inject(fetchInjectable); + instantiate: (di) => { + const lensProxy = di.inject(lensProxyInjectable); + const exitApp = di.inject(exitAppInjectable); + const logger = di.inject(loggerInjectable); + const lensProxyPort = di.inject(lensProxyPortInjectable); + const isWindows = di.inject(isWindowsInjectable); + const showErrorPopup = di.inject(showErrorPopupInjectable); + const buildVersion = di.inject(buildVersionInjectable); + const lensProxyCertificate = di.inject(lensProxyCertificateInjectable); + const fetch = di.inject(fetchInjectable); - try { - logger.info("🔌 Starting LensProxy"); - await lensProxy.listen(); // lensProxy.port available - } catch (error: any) { - showErrorPopup("Lens Error", `Could not start proxy: ${error?.message || "unknown error"}`); - - return exitApp(); - } - - // test proxy connection - try { - logger.info("🔎 Testing LensProxy connection ..."); - const versionResponse = await fetch(`https://127.0.0.1:${lensProxyPort.get()}/version`, { - agent: new Agent({ - ca: lensProxyCertificate.get()?.cert, - }), - }); - - const { version: versionFromProxy } = await versionResponse.json() as { version: string }; - - if (buildVersion.get() !== versionFromProxy) { - logger.error("Proxy server responded with invalid response"); + return { + run: async () => { + try { + logger.info("🔌 Starting LensProxy"); + await lensProxy.listen(); // lensProxy.port available + } catch (error: any) { + showErrorPopup("Lens Error", `Could not start proxy: ${error?.message || "unknown error"}`); return exitApp(); } - logger.info("⚡ LensProxy connection OK"); - } catch (error) { - logger.error(`🛑 LensProxy: failed connection test: ${error}`); + // test proxy connection + try { + logger.info("🔎 Testing LensProxy connection ..."); + const versionResponse = await fetch(`https://127.0.0.1:${lensProxyPort.get()}/version`, { + agent: new Agent({ + ca: lensProxyCertificate.get()?.cert, + }), + }); - const hostsPath = isWindows - ? "C:\\windows\\system32\\drivers\\etc\\hosts" - : "/etc/hosts"; - const message = [ - `Failed connection test: ${error}`, - "Check to make sure that no other versions of Lens are running", - `Check ${hostsPath} to make sure that it is clean and that the localhost loopback is at the top and set to 127.0.0.1`, - "If you have HTTP_PROXY or http_proxy set in your environment, make sure that the localhost and the ipv4 loopback address 127.0.0.1 are added to the NO_PROXY environment variable.", - ]; + const { version: versionFromProxy } = await versionResponse.json() as { version: string }; - showErrorPopup("Lens Proxy Error", message.join("\n\n")); + if (buildVersion.get() !== versionFromProxy) { + logger.error("Proxy server responded with invalid response"); - return exitApp(); - } - }, - runAfter: initializeBuildVersionInjectable, - }), + return exitApp(); + } + + logger.info("⚡ LensProxy connection OK"); + } catch (error) { + logger.error(`🛑 LensProxy: failed connection test: ${error}`); + + const hostsPath = isWindows + ? "C:\\windows\\system32\\drivers\\etc\\hosts" + : "/etc/hosts"; + const message = [ + `Failed connection test: ${error}`, + "Check to make sure that no other versions of Lens are running", + `Check ${hostsPath} to make sure that it is clean and that the localhost loopback is at the top and set to 127.0.0.1`, + "If you have HTTP_PROXY or http_proxy set in your environment, make sure that the localhost and the ipv4 loopback address 127.0.0.1 are added to the NO_PROXY environment variable.", + ]; + + showErrorPopup("Lens Proxy Error", message.join("\n\n")); + + return exitApp(); + } + }, + runAfter: initializeBuildVersionInjectable, + }; + }, causesSideEffects: true, diff --git a/packages/core/src/main/start-main-application/runnables/setup-mobx.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-mobx.injectable.ts index 3352663dd3..a566a9da1b 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-mobx.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-mobx.injectable.ts @@ -4,7 +4,7 @@ */ import * as Mobx from "mobx"; import { getInjectable } from "@ogre-tools/injectable"; -import { beforeElectronIsReadyInjectionToken } from "../runnable-tokens/phases"; +import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; const setupMobxInjectable = getInjectable({ id: "setup-mobx", diff --git a/packages/core/src/main/start-main-application/runnables/setup-proxy-env.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-proxy-env.injectable.ts index 96b3dca4b9..50d93345e6 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-proxy-env.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-proxy-env.injectable.ts @@ -3,37 +3,39 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { beforeElectronIsReadyInjectionToken } from "../runnable-tokens/phases"; +import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; import getCommandLineSwitchInjectable from "../../electron-app/features/get-command-line-switch.injectable"; const setupProxyEnvInjectable = getInjectable({ id: "setup-proxy-env", - instantiate: (di) => ({ - run: () => { - const getCommandLineSwitch = di.inject(getCommandLineSwitchInjectable); - const switchValue = getCommandLineSwitch("proxy-server"); + instantiate: (di) => { + const getCommandLineSwitch = di.inject(getCommandLineSwitchInjectable); - let httpsProxy = process.env.HTTPS_PROXY || process.env.HTTP_PROXY || ""; + return { + run: () => { + const switchValue = getCommandLineSwitch("proxy-server"); - delete process.env.HTTPS_PROXY; - delete process.env.HTTP_PROXY; + let httpsProxy = + process.env.HTTPS_PROXY || process.env.HTTP_PROXY || ""; - if (switchValue !== "") { - httpsProxy = switchValue; - } + delete process.env.HTTPS_PROXY; + delete process.env.HTTP_PROXY; - if (httpsProxy !== "") { - process.env.APP_HTTPS_PROXY = httpsProxy; - } + if (switchValue !== "") { + httpsProxy = switchValue; + } - if (getCommandLineSwitch("proxy-server") !== "") { - process.env.HTTPS_PROXY = getCommandLineSwitch("proxy-server"); - } + if (httpsProxy !== "") { + process.env.APP_HTTPS_PROXY = httpsProxy; + } - return undefined; - }, - }), + if (getCommandLineSwitch("proxy-server") !== "") { + process.env.HTTPS_PROXY = getCommandLineSwitch("proxy-server"); + } + }, + }; + }, injectionToken: beforeElectronIsReadyInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/setup-syncing-of-general-catalog-entities.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-syncing-of-general-catalog-entities.injectable.ts index c263ac6195..431e59bf9d 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-syncing-of-general-catalog-entities.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-syncing-of-general-catalog-entities.injectable.ts @@ -4,18 +4,20 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import syncGeneralCatalogEntitiesInjectable from "../../catalog-sources/sync-general-catalog-entities.injectable"; -import { onLoadOfApplicationInjectionToken } from "../runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const setupSyncingOfGeneralCatalogEntitiesInjectable = getInjectable({ id: "setup-syncing-of-general-catalog-entities", - instantiate: (di) => ({ - run: () => { - const syncGeneralCatalogEntities = di.inject(syncGeneralCatalogEntitiesInjectable); + instantiate: (di) => { + const syncGeneralCatalogEntities = di.inject(syncGeneralCatalogEntitiesInjectable); - syncGeneralCatalogEntities(); - }, - }), + return { + run: () => { + syncGeneralCatalogEntities(); + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/setup-syncing-of-weblinks.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-syncing-of-weblinks.injectable.ts index 058fdcb64b..b7b7af11c6 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-syncing-of-weblinks.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-syncing-of-weblinks.injectable.ts @@ -3,19 +3,21 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { onLoadOfApplicationInjectionToken } from "../runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; import syncWeblinksInjectable from "../../catalog-sources/sync-weblinks.injectable"; const setupSyncingOfWeblinksInjectable = getInjectable({ id: "setup-syncing-of-weblinks", - instantiate: (di) => ({ - run: () => { - const syncWeblinks = di.inject(syncWeblinksInjectable); + instantiate: (di) => { + const syncWeblinks = di.inject(syncWeblinksInjectable); - syncWeblinks(); - }, - }), + return { + run: () => { + syncWeblinks(); + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/setup-system-ca.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-system-ca.injectable.ts index 9d25476278..1142de05f9 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-system-ca.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-system-ca.injectable.ts @@ -3,18 +3,22 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { beforeApplicationIsLoadingInjectionToken } from "../runnable-tokens/phases"; +import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application"; import injectSystemCAsInjectable from "../../../features/certificate-authorities/common/inject-system-cas.injectable"; const setupSystemCaInjectable = getInjectable({ id: "setup-system-ca", - instantiate: (di) => ({ - run: async () => { - const injectSystemCAs = di.inject(injectSystemCAsInjectable); - await injectSystemCAs(); - }, - }), + instantiate: (di) => { + const injectSystemCAs = di.inject(injectSystemCAsInjectable); + + return { + run: async () => { + await injectSystemCAs(); + }, + } + }, + injectionToken: beforeApplicationIsLoadingInjectionToken, }); diff --git a/packages/core/src/main/start-main-application/runnables/show-initial-window.injectable.ts b/packages/core/src/main/start-main-application/runnables/show-initial-window.injectable.ts index a50396d8fa..728a8b480f 100644 --- a/packages/core/src/main/start-main-application/runnables/show-initial-window.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/show-initial-window.injectable.ts @@ -8,7 +8,7 @@ import openDeepLinkInjectable from "../../protocol-handler/lens-protocol-router- import commandLineArgumentsInjectable from "../../utils/command-line-arguments.injectable"; import createFirstApplicationWindowInjectable from "../lens-window/application-window/create-first-application-window.injectable"; import splashWindowInjectable from "../lens-window/splash-window/splash-window.injectable"; -import { showInitialWindowRunnablePhaseInjectionToken } from "../runnable-tokens/phases"; +import { afterApplicationIsLoadedInjectionToken } from "@k8slens/application"; const getDeepLinkUrl = (commandLineArguments: string[]) => ( commandLineArguments @@ -18,31 +18,33 @@ const getDeepLinkUrl = (commandLineArguments: string[]) => ( const showInitialWindowInjectable = getInjectable({ id: "show-initial-window", - instantiate: (di) => ({ - run: async () => { - const shouldStartHidden = di.inject(shouldStartHiddenInjectable); - const shouldStartWindow = !shouldStartHidden; - const createFirstApplicationWindow = di.inject(createFirstApplicationWindowInjectable); - const splashWindow = di.inject(splashWindowInjectable); - const openDeepLink = di.inject(openDeepLinkInjectable); - const commandLineArguments = di.inject(commandLineArgumentsInjectable); + instantiate: (di) => { + const shouldStartHidden = di.inject(shouldStartHiddenInjectable); + const shouldStartWindow = !shouldStartHidden; + const createFirstApplicationWindow = di.inject(createFirstApplicationWindowInjectable); + const splashWindow = di.inject(splashWindowInjectable); + const openDeepLink = di.inject(openDeepLinkInjectable); + const commandLineArguments = di.inject(commandLineArgumentsInjectable); - if (shouldStartWindow) { - const deepLinkUrl = getDeepLinkUrl(commandLineArguments); + return { + run: async () => { + if (shouldStartWindow) { + const deepLinkUrl = getDeepLinkUrl(commandLineArguments); - if (deepLinkUrl) { - await openDeepLink(deepLinkUrl); - } else { - const applicationWindow = createFirstApplicationWindow(); + if (deepLinkUrl) { + await openDeepLink(deepLinkUrl); + } else { + const applicationWindow = createFirstApplicationWindow(); - await applicationWindow.start(); + await applicationWindow.start(); + } + + splashWindow.close(); } - - splashWindow.close(); - } - }, - }), - injectionToken: showInitialWindowRunnablePhaseInjectionToken, + }, + }; + }, + injectionToken: afterApplicationIsLoadedInjectionToken, }); export default showInitialWindowInjectable; diff --git a/packages/core/src/main/start-main-application/runnables/show-loading.injectable.ts b/packages/core/src/main/start-main-application/runnables/show-loading.injectable.ts index 162f6a4937..f4081ee3f4 100644 --- a/packages/core/src/main/start-main-application/runnables/show-loading.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/show-loading.injectable.ts @@ -5,23 +5,24 @@ import { getInjectable } from "@ogre-tools/injectable"; import shouldStartHiddenInjectable from "../../electron-app/features/should-start-hidden.injectable"; import splashWindowInjectable from "../lens-window/splash-window/splash-window.injectable"; -import { showLoadingRunnablePhaseInjectionToken } from "../runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const showLoadingInjectable = getInjectable({ id: "show-loading", + instantiate: (di) => { + const shouldStartHidden = di.inject(shouldStartHiddenInjectable); + const shouldShowLoadingWindow = !shouldStartHidden; + const splashWindow = di.inject(splashWindowInjectable); - instantiate: (di) => ({ - run: async () => { - const shouldStartHidden = di.inject(shouldStartHiddenInjectable); - const shouldShowLoadingWindow = !shouldStartHidden; - const splashWindow = di.inject(splashWindowInjectable); - - if (shouldShowLoadingWindow) { - await splashWindow.start(); - } - }, - }), - injectionToken: showLoadingRunnablePhaseInjectionToken, + return { + run: async () => { + if (shouldShowLoadingWindow) { + await splashWindow.start(); + } + }, + }; + }, + injectionToken: onLoadOfApplicationInjectionToken, }); export default showLoadingInjectable; diff --git a/packages/core/src/main/start-main-application/start-main-application.injectable.ts b/packages/core/src/main/start-main-application/start-main-application.injectable.ts deleted file mode 100644 index 7d7e12f695..0000000000 --- a/packages/core/src/main/start-main-application/start-main-application.injectable.ts +++ /dev/null @@ -1,45 +0,0 @@ -/** - * 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 { runManyFor, runManySyncFor } from "@k8slens/run-many"; -import * as phases from "./runnable-tokens/phases"; -import waitForElectronToBeReadyInjectable from "../electron-app/features/wait-for-electron-to-be-ready.injectable"; - -const startMainApplicationInjectable = getInjectable({ - id: "start-main-application", - - instantiate: (di) => { - const runMany = runManyFor(di); - const runManySync = runManySyncFor(di); - const waitForElectronToBeReady = di.inject(waitForElectronToBeReadyInjectable); - - const appPathsRunnablePhase = runManySync(phases.appPathsRunnablePhaseInjectionToken); - const beforeElectronIsReady = runManySync(phases.beforeElectronIsReadyInjectionToken); - const beforeApplicationIsLoading = runMany(phases.beforeApplicationIsLoadingInjectionToken); - const showLoadingRunnablePhase = runMany(phases.showLoadingRunnablePhaseInjectionToken); - const onLoadOfApplication = runMany(phases.onLoadOfApplicationInjectionToken); - const showInitialWindowRunnablePhase = runMany(phases.showInitialWindowRunnablePhaseInjectionToken); - const afterApplicationIsLoaded = runMany(phases.afterApplicationIsLoadedInjectionToken); - - return () => { - // Stuff happening before application is ready needs to be synchronous because of - // https://github.com/electron/electron/issues/21370 - appPathsRunnablePhase(); - beforeElectronIsReady(); - - return (async () => { - await waitForElectronToBeReady(); - await beforeApplicationIsLoading(); - await showLoadingRunnablePhase(); - await onLoadOfApplication(); - await showInitialWindowRunnablePhase(); - await afterApplicationIsLoaded(); - })(); - }; - }, -}); - -export default startMainApplicationInjectable; diff --git a/packages/core/src/main/stores/init-user-store.injectable.ts b/packages/core/src/main/stores/init-user-store.injectable.ts index d9cc9ee72d..d8e1c0eb36 100644 --- a/packages/core/src/main/stores/init-user-store.injectable.ts +++ b/packages/core/src/main/stores/init-user-store.injectable.ts @@ -5,21 +5,23 @@ import { getInjectable } from "@ogre-tools/injectable"; import userStoreFileNameMigrationInjectable from "../../common/user-store/file-name-migration.injectable"; import userStoreInjectable from "../../common/user-store/user-store.injectable"; -import { beforeApplicationIsLoadingInjectionToken } from "../start-main-application/runnable-tokens/phases"; +import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application"; import initDefaultUpdateChannelInjectable from "../vars/default-update-channel/init.injectable"; const initUserStoreInjectable = getInjectable({ id: "init-user-store", - instantiate: (di) => ({ - run: async () => { - const userStore = di.inject(userStoreInjectable); - const userStoreFileNameMigration = di.inject(userStoreFileNameMigrationInjectable); + instantiate: (di) => { + const userStore = di.inject(userStoreInjectable); + const userStoreFileNameMigration = di.inject(userStoreFileNameMigrationInjectable); - await userStoreFileNameMigration(); - userStore.load(); - }, - runAfter: initDefaultUpdateChannelInjectable, - }), + return { + run: async () => { + await userStoreFileNameMigration(); + userStore.load(); + }, + runAfter: initDefaultUpdateChannelInjectable, + }; + }, injectionToken: beforeApplicationIsLoadingInjectionToken, }); diff --git a/packages/core/src/main/theme/sync-theme-from-os/start-syncing-theme-from-operating-system.injectable.ts b/packages/core/src/main/theme/sync-theme-from-os/start-syncing-theme-from-operating-system.injectable.ts index 8c53850880..290af8576d 100644 --- a/packages/core/src/main/theme/sync-theme-from-os/start-syncing-theme-from-operating-system.injectable.ts +++ b/packages/core/src/main/theme/sync-theme-from-os/start-syncing-theme-from-operating-system.injectable.ts @@ -4,18 +4,20 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import syncThemeFromOperatingSystemInjectable from "../../electron-app/features/sync-theme-from-operating-system.injectable"; -import { onLoadOfApplicationInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const startSyncingThemeFromOperatingSystemInjectable = getInjectable({ id: "start-syncing-theme-from-operating-system", - instantiate: (di) => ({ - run: () => { - const syncTheme = di.inject(syncThemeFromOperatingSystemInjectable); + instantiate: (di) => { + const syncTheme = di.inject(syncThemeFromOperatingSystemInjectable); - syncTheme.start(); - }, - }), + return { + run: () => { + syncTheme.start(); + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/tray/electron-tray/start-tray.injectable.ts b/packages/core/src/main/tray/electron-tray/start-tray.injectable.ts index a7457df25a..25f20f8fad 100644 --- a/packages/core/src/main/tray/electron-tray/start-tray.injectable.ts +++ b/packages/core/src/main/tray/electron-tray/start-tray.injectable.ts @@ -3,19 +3,21 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { onLoadOfApplicationInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; import electronTrayInjectable from "./electron-tray.injectable"; const startTrayInjectable = getInjectable({ id: "start-tray", - instantiate: (di) => ({ - run: () => { - const electronTray = di.inject(electronTrayInjectable); + instantiate: (di) => { + const electronTray = di.inject(electronTrayInjectable); - electronTray.start(); - }, - }), + return { + run: () => { + electronTray.start(); + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/tray/menu-icon/start-reactivity.injectable.ts b/packages/core/src/main/tray/menu-icon/start-reactivity.injectable.ts index 286160e1ee..c646e3200f 100644 --- a/packages/core/src/main/tray/menu-icon/start-reactivity.injectable.ts +++ b/packages/core/src/main/tray/menu-icon/start-reactivity.injectable.ts @@ -3,22 +3,25 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { onLoadOfApplicationInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; import startTrayInjectable from "../electron-tray/start-tray.injectable"; import reactiveTrayMenuIconInjectable from "./reactive.injectable"; const startReactiveTrayMenuIconInjectable = getInjectable({ id: "start-reactive-tray-menu-icon", - instantiate: (di) => ({ - run: () => { - const reactiveTrayMenuIcon = di.inject(reactiveTrayMenuIconInjectable); + instantiate: (di) => { + const reactiveTrayMenuIcon = di.inject(reactiveTrayMenuIconInjectable); - reactiveTrayMenuIcon.start(); - }, + return { + id: "start-reactive-tray-menu-icon", + run: () => { + reactiveTrayMenuIcon.start(); + }, - runAfter: startTrayInjectable, - }), + runAfter: startTrayInjectable, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/tray/reactive-tray-menu-items/start-reactive-tray-menu-items.injectable.ts b/packages/core/src/main/tray/reactive-tray-menu-items/start-reactive-tray-menu-items.injectable.ts index 34a46118ee..c1641709d1 100644 --- a/packages/core/src/main/tray/reactive-tray-menu-items/start-reactive-tray-menu-items.injectable.ts +++ b/packages/core/src/main/tray/reactive-tray-menu-items/start-reactive-tray-menu-items.injectable.ts @@ -4,20 +4,23 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import reactiveTrayMenuItemsInjectable from "./reactive-tray-menu-items.injectable"; -import { onLoadOfApplicationInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; import startTrayInjectable from "../electron-tray/start-tray.injectable"; const startReactiveTrayMenuItemsInjectable = getInjectable({ id: "start-reactive-tray-menu-items", - instantiate: (di) => ({ - run: () => { - const reactiveTrayMenuItems = di.inject(reactiveTrayMenuItemsInjectable); + instantiate: (di) => { + const reactiveTrayMenuItems = di.inject(reactiveTrayMenuItemsInjectable); - reactiveTrayMenuItems.start(); - }, - runAfter: startTrayInjectable, - }), + return { + run: () => { + reactiveTrayMenuItems.start(); + }, + + runAfter: startTrayInjectable, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/user-store/sync-open-at-login-with-os.injectable.ts b/packages/core/src/main/user-store/sync-open-at-login-with-os.injectable.ts index a95f3aa570..628690829e 100644 --- a/packages/core/src/main/user-store/sync-open-at-login-with-os.injectable.ts +++ b/packages/core/src/main/user-store/sync-open-at-login-with-os.injectable.ts @@ -6,26 +6,28 @@ import { getInjectable } from "@ogre-tools/injectable"; import { reaction } from "mobx"; import userStoreInjectable from "../../common/user-store/user-store.injectable"; import setLoginItemSettingsInjectable from "../electron-app/features/set-login-item-settings.injectable"; -import { onLoadOfApplicationInjectionToken } from "../start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const setupSyncOpenAtLoginWithOsInjectable = getInjectable({ id: "setup-sync-open-at-login-with-os", - instantiate: (di) => ({ - run: () => { - const setLoginItemSettings = di.inject(setLoginItemSettingsInjectable); - const userStore = di.inject(userStoreInjectable); + instantiate: (di) => { + const setLoginItemSettings = di.inject(setLoginItemSettingsInjectable); + const userStore = di.inject(userStoreInjectable); - reaction(() => userStore.openAtLogin, openAtLogin => { - setLoginItemSettings({ - openAtLogin, - openAsHidden: true, - args: ["--hidden"], + return { + run: () => { + reaction(() => userStore.openAtLogin, openAtLogin => { + setLoginItemSettings({ + openAtLogin, + openAsHidden: true, + args: ["--hidden"], + }); + }, { + fireImmediately: true, }); - }, { - fireImmediately: true, - }); - }, - }), + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts b/packages/core/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts index 3eaf6d50f2..e0abee681f 100644 --- a/packages/core/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts +++ b/packages/core/src/main/utils/channel/channel-listeners/start-listening-on-channels.injectable.ts @@ -3,22 +3,24 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { onLoadOfApplicationInjectionToken } from "../../../start-main-application/runnable-tokens/phases"; +import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; import listeningOnMessageChannelsInjectable from "../../../../common/utils/channel/listening-on-message-channels.injectable"; import listeningOnRequestChannelsInjectable from "./listening-on-request-channels.injectable"; const startListeningOnChannelsInjectable = getInjectable({ id: "start-listening-on-channels-main", - instantiate: (di) => ({ - run: () => { - const listeningOnMessageChannels = di.inject(listeningOnMessageChannelsInjectable); - const listeningOnRequestChannels = di.inject(listeningOnRequestChannelsInjectable); + instantiate: (di) => { + const listeningOnMessageChannels = di.inject(listeningOnMessageChannelsInjectable); + const listeningOnRequestChannels = di.inject(listeningOnRequestChannelsInjectable); - listeningOnMessageChannels.start(); - listeningOnRequestChannels.start(); - }, - }), + return { + run: () => { + listeningOnMessageChannels.start(); + listeningOnRequestChannels.start(); + }, + }; + }, injectionToken: onLoadOfApplicationInjectionToken, }); diff --git a/packages/core/src/main/vars/build-version/init.injectable.ts b/packages/core/src/main/vars/build-version/init.injectable.ts index 9ea2ee8f4e..100ce9b95a 100644 --- a/packages/core/src/main/vars/build-version/init.injectable.ts +++ b/packages/core/src/main/vars/build-version/init.injectable.ts @@ -3,18 +3,18 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { beforeApplicationIsLoadingInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application"; import buildVersionInjectable from "./build-version.injectable"; const initializeBuildVersionInjectable = getInjectable({ id: "initialize-build-version", - instantiate: (di) => ({ - run: async () => { - const buildVersion = di.inject(buildVersionInjectable); + instantiate: (di) => { + const buildVersion = di.inject(buildVersionInjectable); - await buildVersion.init(); - }, - }), + return { + run: () => buildVersion.init(), + }; + }, injectionToken: beforeApplicationIsLoadingInjectionToken, }); diff --git a/packages/core/src/main/vars/default-update-channel/init.injectable.ts b/packages/core/src/main/vars/default-update-channel/init.injectable.ts index ddde251d44..c7fadbd305 100644 --- a/packages/core/src/main/vars/default-update-channel/init.injectable.ts +++ b/packages/core/src/main/vars/default-update-channel/init.injectable.ts @@ -3,20 +3,20 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { beforeApplicationIsLoadingInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application"; import initReleaseChannelInjectable from "../release-channel/init.injectable"; import defaultUpdateChannelInjectable from "../../../features/application-update/common/selected-update-channel/default-update-channel.injectable"; const initDefaultUpdateChannelInjectable = getInjectable({ id: "init-default-update-channel", - instantiate: (di) => ({ - run: async () => { - const defaultUpdateChannel = di.inject(defaultUpdateChannelInjectable); + instantiate: (di) => { + const defaultUpdateChannel = di.inject(defaultUpdateChannelInjectable); - await defaultUpdateChannel.init(); - }, - runAfter: initReleaseChannelInjectable, - }), + return { + run: async () => await defaultUpdateChannel.init(), + runAfter: initReleaseChannelInjectable, + }; + }, injectionToken: beforeApplicationIsLoadingInjectionToken, }); diff --git a/packages/core/src/main/vars/release-channel/init.injectable.ts b/packages/core/src/main/vars/release-channel/init.injectable.ts index f1da431264..ac72b2c8c3 100644 --- a/packages/core/src/main/vars/release-channel/init.injectable.ts +++ b/packages/core/src/main/vars/release-channel/init.injectable.ts @@ -4,19 +4,19 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import releaseChannelInjectable from "../../../common/vars/release-channel.injectable"; -import { beforeApplicationIsLoadingInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application"; import initSemanticBuildVersionInjectable from "../semantic-build-version/init.injectable"; const initReleaseChannelInjectable = getInjectable({ id: "init-release-channel", - instantiate: (di) => ({ - run: async () => { - const releaseChannel = di.inject(releaseChannelInjectable); + instantiate: (di) => { + const releaseChannel = di.inject(releaseChannelInjectable); - await releaseChannel.init(); - }, - runAfter: initSemanticBuildVersionInjectable, - }), + return { + run: async () => await releaseChannel.init(), + runAfter: initSemanticBuildVersionInjectable, + }; + }, injectionToken: beforeApplicationIsLoadingInjectionToken, }); diff --git a/packages/core/src/main/vars/semantic-build-version/init.injectable.ts b/packages/core/src/main/vars/semantic-build-version/init.injectable.ts index ec05e4d341..b77ccaa1ba 100644 --- a/packages/core/src/main/vars/semantic-build-version/init.injectable.ts +++ b/packages/core/src/main/vars/semantic-build-version/init.injectable.ts @@ -4,18 +4,16 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import buildSemanticVersionInjectable from "../../../common/vars/build-semantic-version.injectable"; -import { beforeApplicationIsLoadingInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { beforeApplicationIsLoadingInjectionToken } from "@k8slens/application"; import initializeBuildVersionInjectable from "../build-version/init.injectable"; const initSemanticBuildVersionInjectable = getInjectable({ id: "init-semantic-build-version", instantiate: (di) => { - return { - run: async () => { - const buildSemanticVersion = di.inject(buildSemanticVersionInjectable); + const buildSemanticVersion = di.inject(buildSemanticVersionInjectable); - await buildSemanticVersion.init(); - }, + return { + run: () => buildSemanticVersion.init(), runAfter: initializeBuildVersionInjectable, }; }, diff --git a/packages/core/src/renderer/bootstrap.global-override-for-injectable.ts b/packages/core/src/renderer/bootstrap.global-override-for-injectable.ts new file mode 100644 index 0000000000..a706ea765f --- /dev/null +++ b/packages/core/src/renderer/bootstrap.global-override-for-injectable.ts @@ -0,0 +1,10 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getGlobalOverride } from "../common/test-utils/get-global-override"; +import bootstrapInjectable from "./bootstrap.injectable"; + +export default getGlobalOverride(bootstrapInjectable, () => ({ + run: () => {}, +})); diff --git a/packages/core/src/renderer/bootstrap.injectable.ts b/packages/core/src/renderer/bootstrap.injectable.ts new file mode 100644 index 0000000000..9bfb492aa9 --- /dev/null +++ b/packages/core/src/renderer/bootstrap.injectable.ts @@ -0,0 +1,28 @@ +/** + * 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 { + afterApplicationIsLoadedInjectionToken, +} from "@k8slens/application"; +import { bootstrap } from "./bootstrap"; +import startFrameInjectable from "./start-frame/start-frame.injectable"; + +const bootstrapInjectable = getInjectable({ + id: "bootstrap", + + instantiate: (di) => ({ + run: async () => { + await bootstrap(di); + }, + + runAfter: di.inject(startFrameInjectable), + }), + + causesSideEffects: true, + + injectionToken: afterApplicationIsLoadedInjectionToken, +}); + +export default bootstrapInjectable; diff --git a/packages/core/src/renderer/bootstrap.tsx b/packages/core/src/renderer/bootstrap.tsx index 88688d4a75..a811f07d5c 100644 --- a/packages/core/src/renderer/bootstrap.tsx +++ b/packages/core/src/renderer/bootstrap.tsx @@ -9,7 +9,9 @@ import React from "react"; import { render, unmountComponentAtNode } from "react-dom"; import { DefaultProps } from "./mui-base-theme"; import { DiContextProvider } from "@ogre-tools/injectable-react"; -import type { DiContainer } from "@ogre-tools/injectable"; +import type { + DiContainerForInjection, +} 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"; @@ -18,13 +20,8 @@ import initClusterFrameInjectable from "./frames/cluster-frame/init-cluster-fram import { Router } from "react-router"; import historyInjectable from "./navigation/history.injectable"; import assert from "assert"; -import startFrameInjectable from "./start-frame/start-frame.injectable"; - -export async function bootstrap(di: DiContainer) { - const startFrame = di.inject(startFrameInjectable); - - await startFrame(); +export async function bootstrap(di: DiContainerForInjection) { const rootElem = document.getElementById("app"); assert(rootElem, "#app MUST exist"); diff --git a/packages/core/src/renderer/components/test-utils/get-application-builder.tsx b/packages/core/src/renderer/components/test-utils/get-application-builder.tsx index 6457bda624..c06ca06a20 100644 --- a/packages/core/src/renderer/components/test-utils/get-application-builder.tsx +++ b/packages/core/src/renderer/components/test-utils/get-application-builder.tsx @@ -23,8 +23,6 @@ import type { NavigateToHelmCharts } from "../../../common/front-end-routing/rou import navigateToHelmChartsInjectable from "../../../common/front-end-routing/routes/cluster/helm/charts/navigate-to-helm-charts.injectable"; import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable"; import type { Cluster } from "../../../common/cluster/cluster"; -import startMainApplicationInjectable from "../../../main/start-main-application/start-main-application.injectable"; -import startFrameInjectable from "../../start-frame/start-frame.injectable"; import type { NamespaceStore } from "../+namespaces/store"; import historyInjectable from "../../navigation/history.injectable"; import type { MinimalTrayMenuItem } from "../../../main/tray/electron-tray/electron-tray.injectable"; @@ -69,6 +67,16 @@ import fsInjectable from "../../../common/fs/fs.injectable"; import joinPathsInjectable from "../../../common/path/join-paths.injectable"; import homeDirectoryPathInjectable from "../../../common/os/home-directory-path.injectable"; import { testUsingFakeTime } from "@k8slens/test-utils"; +import { registerFeature } from "@k8slens/feature-core"; +import { + applicationFeatureForElectronMain, + testUtils as applicationForElectronTestUtils, +} from "@k8slens/application-for-electron-main"; +import { + applicationFeature, + startApplicationInjectionToken, +} from "@k8slens/application"; + type Callback = (di: DiContainer) => void | Promise; @@ -165,9 +173,17 @@ export const getApplicationBuilder = () => { }); runInAction(() => { + registerFeature( + mainDi, + applicationFeature, + applicationFeatureForElectronMain, + ); + mainDi.register(mainExtensionsStateInjectable); }); + applicationForElectronTestUtils.overrideSideEffectsWithFakes(mainDi); + testUsingFakeTime(); const { overrideForWindow, sendToWindow } = overrideChannels(mainDi); @@ -226,6 +242,11 @@ export const getApplicationBuilder = () => { overrideFsWithFakes(windowDi); runInAction(() => { + registerFeature( + windowDi, + applicationFeature, + ); + windowDi.register(rendererExtensionsStateInjectable); }); @@ -253,9 +274,9 @@ export const getApplicationBuilder = () => { await callback(windowDi); } - const startFrame = windowDi.inject(startFrameInjectable); + const startApplication = windowDi.inject(startApplicationInjectionToken); - await startFrame(); + await startApplication(); for (const callback of afterWindowStartCallbacks) { await callback(windowDi); @@ -289,9 +310,9 @@ export const getApplicationBuilder = () => { const namespaces = observable.set(); const namespaceItems = observable.array(); const selectedNamespaces = observable.set(); - const startMainApplication = mainDi.inject(startMainApplicationInjectable); + const startApplication = mainDi.inject(startApplicationInjectionToken); - const startApplication = async ({ shouldStartHidden }: { shouldStartHidden: boolean }) => { + const startApp = async ({ shouldStartHidden }: { shouldStartHidden: boolean }) => { mainDi.inject(lensProxyPortInjectable).set(42); for (const callback of beforeApplicationStartCallbacks) { @@ -299,7 +320,7 @@ export const getApplicationBuilder = () => { } mainDi.override(shouldStartHiddenInjectable, () => shouldStartHidden); - await startMainApplication(); + await startApplication(); for (const callback of afterApplicationStartCallbacks) { await callback(mainDi); @@ -671,11 +692,11 @@ export const getApplicationBuilder = () => { }, startHidden: async () => { - await startApplication({ shouldStartHidden: true }); + await startApp({ shouldStartHidden: true }); }, async render() { - await startApplication({ shouldStartHidden: false }); + await startApp({ shouldStartHidden: false }); return builder .applicationWindow diff --git a/packages/core/src/renderer/create-app.ts b/packages/core/src/renderer/create-app.ts deleted file mode 100644 index e2064a7ae2..0000000000 --- a/packages/core/src/renderer/create-app.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import "./components/app.scss"; - -import { bootstrap } from "./bootstrap"; -import { getInjectable } from "@ogre-tools/injectable"; -import nodeEnvInjectionToken from "../common/vars/node-env-injection-token"; -import { runInAction } from "mobx"; -import { registerInjectables } from "./register-injectables"; -import type { CreateApplication } from "../common/create-app"; -import { getDi } from "./getDi"; - -export const createApplication: CreateApplication = (config) => { - const { mode } = config; - const di = getDi(); - - runInAction(() => { - di.register(getInjectable({ - id: "node-env", - instantiate: () => mode, - injectionToken: nodeEnvInjectionToken, - })); - - registerInjectables(di); - }); - - return { - start: () => bootstrap(di), - di, - }; -}; diff --git a/packages/core/src/renderer/getDi.tsx b/packages/core/src/renderer/getDi.tsx deleted file mode 100644 index 22e545e780..0000000000 --- a/packages/core/src/renderer/getDi.tsx +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ - -import { createContainer } from "@ogre-tools/injectable"; -import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; -import { registerInjectableReact } from "@ogre-tools/injectable-react"; -import { setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; - -export const getDi = () => { - const environment = "renderer"; - const di = createContainer(environment); - - registerMobX(di); - registerInjectableReact(di); - setLegacyGlobalDiForExtensionApi(di, environment); - - return di; -}; diff --git a/packages/core/src/renderer/getDiForUnitTesting.tsx b/packages/core/src/renderer/getDiForUnitTesting.tsx index f5917a048d..6b012cc9f9 100644 --- a/packages/core/src/renderer/getDiForUnitTesting.tsx +++ b/packages/core/src/renderer/getDiForUnitTesting.tsx @@ -4,7 +4,7 @@ */ import { noop, chunk } from "lodash/fp"; -import { isInjectable } from "@ogre-tools/injectable"; +import { createContainer, isInjectable } from "@ogre-tools/injectable"; import requestFromChannelInjectable from "./utils/channel/request-from-channel.injectable"; import { getOverrideFsWithFakes } from "../test-utils/override-fs-with-fakes"; import terminalSpawningPoolInjectable from "./components/dock/terminal/terminal-spawning-pool.injectable"; @@ -15,14 +15,26 @@ import startTopbarStateSyncInjectable from "./components/layout/top-bar/start-st import watchHistoryStateInjectable from "./remote-helpers/watch-history-state.injectable"; import legacyOnChannelListenInjectable from "./ipc/legacy-channel-listen.injectable"; import type { GlobalOverride } from "@k8slens/test-utils"; -import { getDi } from "./getDi"; + +import { + setLegacyGlobalDiForExtensionApi, +} from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; +import { + registerMobX, +} from "@ogre-tools/injectable-extension-for-mobx"; +import { registerInjectableReact } from "@ogre-tools/injectable-react"; export const getDiForUnitTesting = ( opts: { doGeneralOverrides?: boolean } = {}, ) => { const { doGeneralOverrides = false } = opts; - const di = getDi(); + const environment = "renderer"; + const di = createContainer(environment); + + registerMobX(di); + registerInjectableReact(di); + setLegacyGlobalDiForExtensionApi(di, environment); di.preventSideEffects(); diff --git a/packages/core/src/renderer/library.ts b/packages/core/src/renderer/library.ts index aa9c1fc907..41c7dea0e7 100644 --- a/packages/core/src/renderer/library.ts +++ b/packages/core/src/renderer/library.ts @@ -7,6 +7,12 @@ import React from "react"; import ReactDOM from "react-dom"; // @experimental +export type { + Environments, +} from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; + +export { nodeEnvInjectionToken } from "../common/vars/node-env-injection-token"; +export { registerLensCore } from "./register-lens-core"; export { React, ReactDOM }; export * as Mobx from "mobx"; export * as MobxReact from "mobx-react"; @@ -14,5 +20,3 @@ export * as ReactRouter from "react-router"; export * as ReactRouterDom from "react-router-dom"; export * as rendererExtensionApi from "../extensions/renderer-api"; export * as commonExtensionApi from "../extensions/common-api"; -export { createApplication } from "./create-app"; -export type { CreateApplication, Application, ApplicationConfig } from "../common/create-app"; diff --git a/packages/core/src/main/register-injectables.ts b/packages/core/src/renderer/register-lens-core.ts similarity index 66% rename from packages/core/src/main/register-injectables.ts rename to packages/core/src/renderer/register-lens-core.ts index eb18df3d3f..8031ea47e7 100644 --- a/packages/core/src/main/register-injectables.ts +++ b/packages/core/src/renderer/register-lens-core.ts @@ -2,19 +2,28 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ + import type { DiContainer } from "@ogre-tools/injectable"; import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; import { runInAction } from "mobx"; +import type { + Environments, +} from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; +import { + setLegacyGlobalDiForExtensionApi, +} from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; + +export function registerLensCore(di: DiContainer, environment: Environments) { + setLegacyGlobalDiForExtensionApi(di, environment); -export function registerInjectables(di: DiContainer) { runInAction(() => { autoRegister({ di, targetModule: module, getRequireContexts: () => [ require.context("./", true, CONTEXT_MATCHER_FOR_NON_FEATURES), - require.context("../extensions", true, CONTEXT_MATCHER_FOR_NON_FEATURES), require.context("../common", true, CONTEXT_MATCHER_FOR_NON_FEATURES), + require.context("../extensions", true, CONTEXT_MATCHER_FOR_NON_FEATURES), require.context("../features", true, CONTEXT_MATCHER_FOR_FEATURES), ], }); diff --git a/packages/core/src/renderer/start-frame/start-frame.injectable.ts b/packages/core/src/renderer/start-frame/start-frame.injectable.ts index b19e72e8d0..b4bddc9c30 100644 --- a/packages/core/src/renderer/start-frame/start-frame.injectable.ts +++ b/packages/core/src/renderer/start-frame/start-frame.injectable.ts @@ -6,11 +6,13 @@ import { getInjectable } from "@ogre-tools/injectable"; import { runManyFor } from "@k8slens/run-many"; import * as tokens from "../before-frame-starts/tokens"; import currentlyInClusterFrameInjectable from "../routes/currently-in-cluster-frame.injectable"; +import { + afterApplicationIsLoadedInjectionToken, +} from "@k8slens/application"; const startFrameInjectable = getInjectable({ id: "start-frame", - // TODO: Consolidate contents of bootstrap.tsx here instantiate: (di) => { const runMany = runManyFor(di); const beforeFrameStartsFirst = runMany(tokens.beforeFrameStartsFirstInjectionToken); @@ -21,24 +23,28 @@ const startFrameInjectable = getInjectable({ const beforeClusterFrameStartsSecond = runMany(tokens.beforeClusterFrameStartsSecondInjectionToken); const currentlyInClusterFrame = di.inject(currentlyInClusterFrameInjectable); - return async () => { - await beforeFrameStartsFirst(); + return { + run: async () => { + await beforeFrameStartsFirst(); - if (currentlyInClusterFrame) { - await beforeClusterFrameStartsFirst(); - } else { - await beforeMainFrameStartsFirst(); - } + if (currentlyInClusterFrame) { + await beforeClusterFrameStartsFirst(); + } else { + await beforeMainFrameStartsFirst(); + } - await beforeFrameStartsSecond(); + await beforeFrameStartsSecond(); - if (currentlyInClusterFrame) { - await beforeClusterFrameStartsSecond(); - } else { - await beforeMainFrameStartsSecond(); - } + if (currentlyInClusterFrame) { + await beforeClusterFrameStartsSecond(); + } else { + await beforeMainFrameStartsSecond(); + } + }, }; }, + + injectionToken: afterApplicationIsLoadedInjectionToken, }); export default startFrameInjectable; diff --git a/packages/ensure-binaries/package.json b/packages/ensure-binaries/package.json index e7f6dd4d12..edd9c1d5b1 100644 --- a/packages/ensure-binaries/package.json +++ b/packages/ensure-binaries/package.json @@ -32,7 +32,7 @@ }, "devDependencies": { "@swc/cli": "^0.1.61", - "@swc/core": "^1.3.35", + "@swc/core": "^1.3.37", "@types/cli-progress": "^3.11.0", "@types/gunzip-maybe": "^1.4.0", "@types/node": "^16.18.11", diff --git a/packages/extension-api/package.json b/packages/extension-api/package.json index 5cd240bad1..f89f9653ba 100644 --- a/packages/extension-api/package.json +++ b/packages/extension-api/package.json @@ -39,6 +39,7 @@ "style-loader": "^3.3.1", "ts-loader": "^9.4.2", "ts-node": "^10.9.1", + "typed-emitter": "^2.1.0", "typedoc": "0.23.25", "typedoc-plugin-markdown": "^3.13.6", "typescript": "^4.9.5", diff --git a/packages/generate-tray-icons/package.json b/packages/generate-tray-icons/package.json index b75562e5c9..bab81b6be5 100644 --- a/packages/generate-tray-icons/package.json +++ b/packages/generate-tray-icons/package.json @@ -23,7 +23,7 @@ }, "devDependencies": { "@swc/cli": "^0.1.61", - "@swc/core": "^1.3.35", + "@swc/core": "^1.3.37", "@types/jsdom": "^20.0.1", "@types/node": "^18.11.18", "@types/sharp": "^0.31.1", diff --git a/packages/infrastructure/jest/package.json b/packages/infrastructure/jest/package.json index 5488a69729..3e9bbb0815 100644 --- a/packages/infrastructure/jest/package.json +++ b/packages/infrastructure/jest/package.json @@ -20,7 +20,7 @@ "license": "MIT", "homepage": "https://github.com/lensapp/lens", "dependencies": { - "@swc/core": "^1.3.20", + "@swc/core": "^1.3.37", "@swc/jest": "^0.2.23", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", diff --git a/packages/open-lens/package.json b/packages/open-lens/package.json index 216705c111..df5e3034d3 100644 --- a/packages/open-lens/package.json +++ b/packages/open-lens/package.json @@ -196,17 +196,20 @@ }, "dependencies": { "@k8slens/application": "^6.5.0-alpha.0", + "@k8slens/feature-core": "^6.5.0-alpha.0", + "@k8slens/application-for-electron-main": "^6.5.0-alpha.0", "@k8slens/core": "^6.5.0-alpha.0", "@k8slens/ensure-binaries": "^6.5.0-alpha.0", "@k8slens/generate-tray-icons": "^6.5.0-alpha.0", "@k8slens/run-many": "^1.0.0", "@k8slens/test-utils": "^1.0.0", "@k8slens/utilities": "^1.0.0", - "@ogre-tools/fp": "^15.1.1", - "@ogre-tools/injectable": "^15.1.1", - "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.1", - "@ogre-tools/injectable-extension-for-mobx": "^15.1.1", - "@ogre-tools/injectable-react": "^15.1.1", + "@ogre-tools/fp": "^15.1.2", + "@ogre-tools/injectable": "^15.1.2", + "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", + "@ogre-tools/injectable-extension-for-mobx": "^15.1.2", + "@ogre-tools/injectable-react": "^15.1.2", + "@ogre-tools/injectable-utils": "^15.1.2", "mobx": "^6.8.0", "rimraf": "^4.1.2" }, @@ -215,7 +218,7 @@ "@k8slens/node-fetch": "^6.5.0-alpha.0", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.10", "@swc/cli": "^0.1.61", - "@swc/core": "^1.3.35", + "@swc/core": "^1.3.37", "@swc/jest": "^0.2.24", "@types/byline": "^4.2.33", "@types/chart.js": "^2.9.36", diff --git a/packages/open-lens/src/main/index.ts b/packages/open-lens/src/main/index.ts index 39500b2240..5329be4595 100644 --- a/packages/open-lens/src/main/index.ts +++ b/packages/open-lens/src/main/index.ts @@ -1,15 +1,30 @@ import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; import { runInAction } from "mobx"; -import { createApplication, mainExtensionApi as Main, commonExtensionApi as Common } from "@k8slens/core/main"; +import { + mainExtensionApi as Main, + commonExtensionApi as Common, + registerLensCore, +} from "@k8slens/core/main"; +import { createContainer } from "@ogre-tools/injectable"; +import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; +import { registerFeature } from "@k8slens/feature-core"; +import { applicationFeature, startApplicationInjectionToken } from '@k8slens/application' +import { applicationFeatureForElectronMain } from '@k8slens/application-for-electron-main' -const app = createApplication({ - mode: process.env.NODE_ENV || "development" -}); +const environment = "main"; + +const di = createContainer(environment); + +registerMobX(di); runInAction(() => { + registerLensCore(di, environment); + + registerFeature(di, applicationFeature, applicationFeatureForElectronMain); + try { autoRegister({ - di: app.di, + di, targetModule: module, getRequireContexts: () => [ require.context("./", true, CONTEXT_MATCHER_FOR_NON_FEATURES), @@ -22,7 +37,9 @@ runInAction(() => { } }); -app.start().catch((error) => { +const startApplication = di.inject(startApplicationInjectionToken); + +startApplication().catch((error) => { console.error(error); process.exit(1); }) diff --git a/packages/open-lens/src/main/node-env.injectable.ts b/packages/open-lens/src/main/node-env.injectable.ts new file mode 100644 index 0000000000..750c918555 --- /dev/null +++ b/packages/open-lens/src/main/node-env.injectable.ts @@ -0,0 +1,8 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import { nodeEnvInjectionToken } from "@k8slens/core/main"; + +export const nodeEnvInjectable = getInjectable({ + id: "node-env", + instantiate: () => process.env.NODE_ENV || "development", + injectionToken: nodeEnvInjectionToken, +}); diff --git a/packages/open-lens/src/renderer/index.ts b/packages/open-lens/src/renderer/index.ts index ed28f26d3a..7bdbd2ea3f 100644 --- a/packages/open-lens/src/renderer/index.ts +++ b/packages/open-lens/src/renderer/index.ts @@ -1,15 +1,32 @@ import "@k8slens/core/styles"; import { runInAction } from "mobx"; -import { createApplication, rendererExtensionApi as Renderer, commonExtensionApi as Common } from "@k8slens/core/renderer"; +import { + rendererExtensionApi as Renderer, + commonExtensionApi as Common, + registerLensCore, +} from "@k8slens/core/renderer"; import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; +import { registerFeature } from "@k8slens/feature-core"; +import { + applicationFeature, + startApplicationInjectionToken +} from "@k8slens/application"; +import { createContainer } from "@ogre-tools/injectable"; +import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx"; +import { registerInjectableReact } from "@ogre-tools/injectable-react"; -const app = createApplication({ - mode: process.env.NODE_ENV || "development" -}); +const environment = "main"; + +const di = createContainer(environment); runInAction(() => { + registerMobX(di); + registerInjectableReact(di); + registerLensCore(di, environment); + registerFeature(di, applicationFeature); + autoRegister({ - di: app.di, + di, targetModule: module, getRequireContexts: () => [ require.context("./", true, CONTEXT_MATCHER_FOR_NON_FEATURES), @@ -18,7 +35,9 @@ runInAction(() => { }); }); -app.start(); +const startApplication = di.inject(startApplicationInjectionToken); + +startApplication(); export { React, diff --git a/packages/open-lens/src/renderer/node-env.injectable.ts b/packages/open-lens/src/renderer/node-env.injectable.ts new file mode 100644 index 0000000000..8c50e853f1 --- /dev/null +++ b/packages/open-lens/src/renderer/node-env.injectable.ts @@ -0,0 +1,8 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import { nodeEnvInjectionToken } from "@k8slens/core/renderer"; + +export const nodeEnvInjectable = getInjectable({ + id: "node-env", + instantiate: () => process.env.NODE_ENV || "development", + injectionToken: nodeEnvInjectionToken, +}); diff --git a/packages/open-lens/webpack/renderer.ts b/packages/open-lens/webpack/renderer.ts index cd3f65e978..e46487c6de 100644 --- a/packages/open-lens/webpack/renderer.ts +++ b/packages/open-lens/webpack/renderer.ts @@ -14,7 +14,7 @@ import CopyPlugin from "copy-webpack-plugin"; import type { WebpackPluginInstance } from "webpack"; import { DefinePlugin } from "webpack"; - import { assetsFolderName, isDevelopment, rendererDir, buildDir, htmlTemplate, publicPath, sassCommonVars } from "./vars"; + import { assetsFolderName, isDevelopment, rendererDir, buildDir, htmlTemplate, publicPath } from "./vars"; import { platform } from "process"; const renderer: webpack.Configuration = { diff --git a/packages/release-tool/package.json b/packages/release-tool/package.json index ca3df9364b..1b3a0a1e15 100644 --- a/packages/release-tool/package.json +++ b/packages/release-tool/package.json @@ -15,7 +15,7 @@ "type": "module", "devDependencies": { "@swc/cli": "^0.1.61", - "@swc/core": "^1.3.35", + "@swc/core": "^1.3.37", "@types/inquirer": "^9.0.3", "@types/node": "^16.18.11", "@types/semver": "^7.3.13", diff --git a/packages/release-tool/src/index.ts b/packages/release-tool/src/index.ts index 8c1e465ffd..2632d883f0 100755 --- a/packages/release-tool/src/index.ts +++ b/packages/release-tool/src/index.ts @@ -145,6 +145,14 @@ function formatSemverForMilestone(version: SemVer): string { return `${version.major}.${version.minor}.${version.patch}`; } +function formatVersionForPickingPrs(version: SemVer): string { + if (version.prerelease.length > 0) { + return `${version.major}.${version.minor}.${version.patch}`; + } + + return `${version.major}.${version.minor}.${version.patch+1}`; +} + async function createReleaseBranchAndCommit(prBase: string, version: SemVer, prBody: string): Promise { const prBranch = `release/v${version.format()}`; @@ -182,9 +190,10 @@ function sortExtendedGithubPrData(left: ExtendedGithubPrData, right: ExtendedGit return -1; } -async function getRelevantPRs(milestone: string, previousReleasedVersion: string): Promise { +async function getRelevantPRs(previousReleasedVersion: string): Promise { console.log("retrieving previous 200 PRs..."); + const milestone = formatVersionForPickingPrs(await getCurrentVersionOfSubPackage("core")); const getMergedPrsArgs = [ "gh", "pr", @@ -326,8 +335,7 @@ async function createRelease(): Promise { await bumpPackageVersions(); } - const prMilestone = formatSemverForMilestone(await getCurrentVersionOfSubPackage("core")); - const relevantPrs = await getRelevantPRs(prMilestone, previousReleasedVersion); + const relevantPrs = await getRelevantPRs(previousReleasedVersion); const selectedPrs = await pickRelevantPrs(relevantPrs, isMasterBranch); const prBody = formatChangelog(previousReleasedVersion, selectedPrs); diff --git a/packages/semver/package.json b/packages/semver/package.json index 2b8b4275d7..ce6e5dbf8b 100644 --- a/packages/semver/package.json +++ b/packages/semver/package.json @@ -15,7 +15,7 @@ }, "devDependencies": { "@swc/cli": "^0.1.61", - "@swc/core": "^1.3.35", + "@swc/core": "^1.3.37", "@types/command-line-args": "^5.2.0", "@types/node": "^16.18.11", "@types/semver": "^7.3.13", diff --git a/packages/technical-features/application/README.md b/packages/technical-features/application/README.md deleted file mode 100644 index 451e211c85..0000000000 --- a/packages/technical-features/application/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# @k8slens/application - -This package contains stuff related to creating Lens-applications. - -In the beginning it will contain just the injection tokens used to configure the application. - -## Install -```bash -$ npm install @k8slens/application -``` - - -## Usage - -As of now, this package doesn't do anything alone. It just provides you way to register implementation for contract. - -Future ambition is that all stuff related to how applications are built will be relocated here. - diff --git a/packages/technical-features/application/agnostic/README.md b/packages/technical-features/application/agnostic/README.md new file mode 100644 index 0000000000..d7fd9493ac --- /dev/null +++ b/packages/technical-features/application/agnostic/README.md @@ -0,0 +1,39 @@ +# @k8slens/application + +This package contains stuff related to creating Lens-applications. + +# Usage + +```bash +$ npm install @k8slens/application-for-electron-main +``` + +```typescript +import { applicationFeature, startApplicationInjectionToken } from "@k8slens/application"; +import { registerFeature } from "@k8slens/feature-core"; +import { createContainer } from "@ogre-tools/injectable"; + +const di = createContainer("some-container"); + +registerFeature(di, applicationFeature); + +const startApplication = di.inject(startApplicationInjectionToken); + +startApplication(); +``` + + +## Features + +#### Start application +`startApplicationInjectionToken` + +Starts the application and calls timeslots in specified order. Check for timeslots for more info. + +## Extendability + +#### Timeslots + +1. `beforeApplicationIsLoadingInjectionToken` +2. `onLoadOfApplicationInjectionToken` +3. `afterApplicationIsLoadedInjectionToken` diff --git a/packages/technical-features/application/agnostic/index.ts b/packages/technical-features/application/agnostic/index.ts new file mode 100644 index 0000000000..559a91582b --- /dev/null +++ b/packages/technical-features/application/agnostic/index.ts @@ -0,0 +1,11 @@ +export { applicationFeature } from "./src/feature"; + +export { onLoadOfApplicationInjectionToken } from "./src/start-application/timeslots/on-load-of-application-injection-token"; +export { beforeApplicationIsLoadingInjectionToken } from "./src/start-application/timeslots/before-application-is-loading-injection-token"; +export { afterApplicationIsLoadedInjectionToken } from "./src/start-application/timeslots/after-application-is-loaded-injection-token"; + +export type { StartApplication } from "./src/start-application/start-application.injectable"; +export { startApplicationInjectionToken } from "./src/start-application/start-application.injectable"; + +export { applicationInformationToken } from "./src/application-information-token"; +export type { ApplicationInformation } from "./src/application-information-token"; diff --git a/packages/technical-features/application/jest.config.js b/packages/technical-features/application/agnostic/jest.config.js similarity index 87% rename from packages/technical-features/application/jest.config.js rename to packages/technical-features/application/agnostic/jest.config.js index 23be80353b..6d3d6ff231 100644 --- a/packages/technical-features/application/jest.config.js +++ b/packages/technical-features/application/agnostic/jest.config.js @@ -1,2 +1,2 @@ module.exports = - require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; + require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode; diff --git a/packages/technical-features/application/package.json b/packages/technical-features/application/agnostic/package.json similarity index 67% rename from packages/technical-features/application/package.json rename to packages/technical-features/application/agnostic/package.json index eca9d76868..35b555ac2e 100644 --- a/packages/technical-features/application/package.json +++ b/packages/technical-features/application/agnostic/package.json @@ -13,7 +13,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/lensapp/monorepo.git" + "url": "git+https://github.com/lensapp/lens.git" }, "main": "dist/index.js", "types": "dist/index.d.ts", @@ -29,8 +29,15 @@ "test": "jest --coverage --runInBand" }, "peerDependencies": { - "@ogre-tools/fp": "^15.1.1", - "@ogre-tools/injectable": "^15.1.1", + "@k8slens/feature-core": "^6.5.0-alpha.0", + "@ogre-tools/fp": "^15.1.2", + "@ogre-tools/injectable": "^15.1.2", + "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", + "@ogre-tools/injectable-utils": "^15.1.2", "lodash": "^4.17.15" + }, + + "devDependencies": { + "@async-fn/jest": "^1.6.4" } } diff --git a/packages/technical-features/application/src/application-information-token.ts b/packages/technical-features/application/agnostic/src/application-information-token.ts similarity index 100% rename from packages/technical-features/application/src/application-information-token.ts rename to packages/technical-features/application/agnostic/src/application-information-token.ts diff --git a/packages/technical-features/application/agnostic/src/feature.ts b/packages/technical-features/application/agnostic/src/feature.ts new file mode 100644 index 0000000000..3ad2a495e6 --- /dev/null +++ b/packages/technical-features/application/agnostic/src/feature.ts @@ -0,0 +1,17 @@ +import { getFeature } from "@k8slens/feature-core"; +import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; + +export const applicationFeature = getFeature({ + id: "application", + + register: (di) => { + autoRegister({ + di, + targetModule: module, + + getRequireContexts: () => [ + require.context("./", true, /\.injectable\.(ts|tsx)$/), + ], + }); + }, +}); diff --git a/packages/technical-features/application/agnostic/src/start-application/start-application.injectable.ts b/packages/technical-features/application/agnostic/src/start-application/start-application.injectable.ts new file mode 100644 index 0000000000..4d9d8c9da2 --- /dev/null +++ b/packages/technical-features/application/agnostic/src/start-application/start-application.injectable.ts @@ -0,0 +1,42 @@ +import { getInjectable, getInjectionToken } from "@ogre-tools/injectable"; +import { runManyFor } from "@ogre-tools/injectable-utils"; +import { beforeApplicationIsLoadingInjectionToken } from "./timeslots/before-application-is-loading-injection-token"; +import { onLoadOfApplicationInjectionToken } from "./timeslots/on-load-of-application-injection-token"; +import { afterApplicationIsLoadedInjectionToken } from "./timeslots/after-application-is-loaded-injection-token"; + +export type StartApplication = () => Promise; + +export const startApplicationInjectionToken = + getInjectionToken({ + id: "start-application-injection-token", + }); + +const startApplicationInjectable = getInjectable({ + id: "start-application", + + instantiate: (di): StartApplication => { + const runManyAsync = runManyFor(di) + + const beforeApplicationIsLoading = runManyAsync( + beforeApplicationIsLoadingInjectionToken + ); + + const onLoadOfApplication = runManyAsync(onLoadOfApplicationInjectionToken); + + const afterApplicationIsLoaded = runManyAsync( + afterApplicationIsLoadedInjectionToken + ); + + return async () => { + await beforeApplicationIsLoading(); + + await onLoadOfApplication(); + + await afterApplicationIsLoaded(); + }; + }, + + injectionToken: startApplicationInjectionToken, +}); + +export default startApplicationInjectable; diff --git a/packages/technical-features/application/agnostic/src/start-application/starting-of-application.test.ts b/packages/technical-features/application/agnostic/src/start-application/starting-of-application.test.ts new file mode 100644 index 0000000000..37453d4ba3 --- /dev/null +++ b/packages/technical-features/application/agnostic/src/start-application/starting-of-application.test.ts @@ -0,0 +1,82 @@ +import { + createContainer, + DiContainer, + getInjectable, +} from "@ogre-tools/injectable"; +import { registerFeature } from "@k8slens/feature-core"; +import { applicationFeature } from "../feature"; +import { startApplicationInjectionToken } from "./start-application.injectable"; +import { beforeApplicationIsLoadingInjectionToken } from "./timeslots/before-application-is-loading-injection-token"; +import asyncFn, { AsyncFnMock } from "@async-fn/jest"; +import { onLoadOfApplicationInjectionToken } from "./timeslots/on-load-of-application-injection-token"; +import { afterApplicationIsLoadedInjectionToken } from "./timeslots/after-application-is-loaded-injection-token"; + +describe("starting-of-application", () => { + let di: DiContainer; + + let beforeApplicationIsLoadingMock: AsyncFnMock<() => Promise>; + let onLoadOfApplicationMock: AsyncFnMock<() => Promise>; + let afterApplicationIsLoadedMock: AsyncFnMock<() => Promise>; + + beforeEach(() => { + di = createContainer("irrelevant"); + + registerFeature(di, applicationFeature); + + beforeApplicationIsLoadingMock = asyncFn(); + onLoadOfApplicationMock = asyncFn(); + afterApplicationIsLoadedMock = asyncFn(); + + const beforeApplicationIsLoadingInjectable = getInjectable({ + id: "before-application-is-loading", + instantiate: () => ({ run: beforeApplicationIsLoadingMock }), + injectionToken: beforeApplicationIsLoadingInjectionToken, + }); + + const onLoadOfApplicationInjectable = getInjectable({ + id: "on-load-of-application", + instantiate: () => ({ run: onLoadOfApplicationMock }), + injectionToken: onLoadOfApplicationInjectionToken, + }); + + const afterApplicationIsLoadedInjectable = getInjectable({ + id: "after-application-is-loaded", + instantiate: () => ({ run: afterApplicationIsLoadedMock }), + injectionToken: afterApplicationIsLoadedInjectionToken, + }); + + di.register( + beforeApplicationIsLoadingInjectable, + onLoadOfApplicationInjectable, + afterApplicationIsLoadedInjectable + ); + }); + + describe("when application is started", () => { + beforeEach(() => { + const startApplication = di.inject(startApplicationInjectionToken); + + startApplication(); + }); + + it("calls runnables registered in before application is loading", () => { + expect(beforeApplicationIsLoadingMock).toHaveBeenCalled(); + }); + + describe("when runnables in before application is loading resolve", () => { + beforeEach(async () => { + await beforeApplicationIsLoadingMock.resolve(); + }); + + it("calls runnables registered in on load of application", () => { + expect(onLoadOfApplicationMock).toHaveBeenCalled(); + }); + + it("when runnables in before application is loading resolve, calls runnables registered in after load of application", async () => { + await onLoadOfApplicationMock.resolve(); + + expect(afterApplicationIsLoadedMock).toHaveBeenCalled(); + }); + }); + }); +}); diff --git a/packages/technical-features/application/agnostic/src/start-application/timeslots/after-application-is-loaded-injection-token.ts b/packages/technical-features/application/agnostic/src/start-application/timeslots/after-application-is-loaded-injection-token.ts new file mode 100644 index 0000000000..6e04840f6e --- /dev/null +++ b/packages/technical-features/application/agnostic/src/start-application/timeslots/after-application-is-loaded-injection-token.ts @@ -0,0 +1,7 @@ +import { getInjectionToken } from "@ogre-tools/injectable"; +import type { Runnable } from "@ogre-tools/injectable-utils"; + +export const afterApplicationIsLoadedInjectionToken = + getInjectionToken({ + id: "after-application-is-loaded-injection-token", + }); diff --git a/packages/technical-features/application/agnostic/src/start-application/timeslots/before-application-is-loading-injection-token.ts b/packages/technical-features/application/agnostic/src/start-application/timeslots/before-application-is-loading-injection-token.ts new file mode 100644 index 0000000000..54bff82be5 --- /dev/null +++ b/packages/technical-features/application/agnostic/src/start-application/timeslots/before-application-is-loading-injection-token.ts @@ -0,0 +1,7 @@ +import { getInjectionToken } from "@ogre-tools/injectable"; +import type { Runnable } from "@ogre-tools/injectable-utils"; + +export const beforeApplicationIsLoadingInjectionToken = + getInjectionToken({ + id: "before-application-is-loading-injection-token", + }); diff --git a/packages/technical-features/application/agnostic/src/start-application/timeslots/on-load-of-application-injection-token.ts b/packages/technical-features/application/agnostic/src/start-application/timeslots/on-load-of-application-injection-token.ts new file mode 100644 index 0000000000..c732329e29 --- /dev/null +++ b/packages/technical-features/application/agnostic/src/start-application/timeslots/on-load-of-application-injection-token.ts @@ -0,0 +1,6 @@ +import { getInjectionToken } from "@ogre-tools/injectable"; +import type { Runnable } from "@ogre-tools/injectable-utils"; + +export const onLoadOfApplicationInjectionToken = getInjectionToken({ + id: "on-load-of-application", +}); diff --git a/packages/technical-features/application/tsconfig.json b/packages/technical-features/application/agnostic/tsconfig.json similarity index 100% rename from packages/technical-features/application/tsconfig.json rename to packages/technical-features/application/agnostic/tsconfig.json diff --git a/packages/technical-features/application/webpack.config.js b/packages/technical-features/application/agnostic/webpack.config.js similarity index 100% rename from packages/technical-features/application/webpack.config.js rename to packages/technical-features/application/agnostic/webpack.config.js diff --git a/packages/technical-features/application/electron-main/README.md b/packages/technical-features/application/electron-main/README.md new file mode 100644 index 0000000000..6b4f590464 --- /dev/null +++ b/packages/technical-features/application/electron-main/README.md @@ -0,0 +1,35 @@ +# @k8slens/application-for-electron-main + +This Feature extends `@k8slens/application` with Electron specifics. + +# Usage +```bash +$ npm install @k8slens/application-for-electron-main +``` + +```typescript +import { applicationFeature, startApplicationInjectionToken } from "@k8slens/application"; +import { applicationFeatureForElectronMain } from "@k8slens/application-for-electron-main"; +import { registerFeature } from "@k8slens/feature-core"; +import { createContainer } from "@ogre-tools/injectable"; + +const di = createContainer("some-container"); + +registerFeature(di, applicationFeature, applicationFeatureForElectronMain); + +const startApplication = di.inject(startApplicationInjectionToken); + +startApplication(); +``` + +# Extendability + +### Timeslots + +#### `beforeAnythingInjectionToken` + +Runnables registered here will be called before anything else. **Special requirement** here is that everything here needs to be synchronous. + +#### `beforeElectronIsReadyInjectionToken` + +Runnables registered here will be called right after runnables in `beforeAnythingInjectionToken` but still before we are sure that Electron application is ready (`electron.app.whenReady()`). **Special requirement** here is that everything here needs to be synchronous. diff --git a/packages/technical-features/application/electron-main/index.ts b/packages/technical-features/application/electron-main/index.ts new file mode 100644 index 0000000000..d3d92e0aa3 --- /dev/null +++ b/packages/technical-features/application/electron-main/index.ts @@ -0,0 +1,8 @@ +import { overrideSideEffectsWithFakes } from "./src/override-side-effects-with-fakes"; + +export { beforeElectronIsReadyInjectionToken } from "./src/start-application/timeslots/before-electron-is-ready-injection-token"; +export { beforeAnythingInjectionToken } from "./src/start-application/timeslots/before-anything-injection-token"; + +export { applicationFeatureForElectronMain } from "./src/feature"; + +export const testUtils = { overrideSideEffectsWithFakes } diff --git a/packages/technical-features/application/electron-main/jest.config.js b/packages/technical-features/application/electron-main/jest.config.js new file mode 100644 index 0000000000..6d3d6ff231 --- /dev/null +++ b/packages/technical-features/application/electron-main/jest.config.js @@ -0,0 +1,2 @@ +module.exports = + require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode; diff --git a/packages/technical-features/application/electron-main/package.json b/packages/technical-features/application/electron-main/package.json new file mode 100644 index 0000000000..eb1b42c2c8 --- /dev/null +++ b/packages/technical-features/application/electron-main/package.json @@ -0,0 +1,44 @@ +{ + "name": "@k8slens/application-for-electron-main", + "private": false, + "version": "6.5.0-alpha.0", + "description": "Electron's main specifics for creating Lens applications", + "type": "commonjs", + "files": [ + "dist" + ], + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/lensapp/lens.git" + }, + "main": "dist/index.js", + "types": "dist/index.d.ts", + "author": { + "name": "OpenLens Authors", + "email": "info@k8slens.dev" + }, + "license": "MIT", + "homepage": "https://github.com/lensapp/lens", + "scripts": { + "build": "webpack", + "dev": "webpack --mode=development --watch", + "test": "jest --coverage --runInBand" + }, + "peerDependencies": { + "@k8slens/feature-core": "^6.5.0-alpha.0", + "@k8slens/application": "^6.5.0-alpha.0", + "@ogre-tools/injectable": "^15.1.2", + "@ogre-tools/injectable-extension-for-auto-registration": "^15.1.2", + "@ogre-tools/injectable-utils": "^15.1.2", + "electron": "^19.1.9" + }, + + "devDependencies": { + "@async-fn/jest": "^1.6.4", + "@ogre-tools/test-utils": "^15.1.2" + } +} diff --git a/packages/technical-features/application/electron-main/src/electron/electron-app.injectable.ts b/packages/technical-features/application/electron-main/src/electron/electron-app.injectable.ts new file mode 100644 index 0000000000..52b037c4e1 --- /dev/null +++ b/packages/technical-features/application/electron-main/src/electron/electron-app.injectable.ts @@ -0,0 +1,14 @@ +/** + * 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 { app } from "electron"; + +const electronAppInjectable = getInjectable({ + id: "electron-app", + instantiate: () => app, + causesSideEffects: true, +}); + +export default electronAppInjectable; diff --git a/packages/technical-features/application/electron-main/src/electron/electron-app.test.ts b/packages/technical-features/application/electron-main/src/electron/electron-app.test.ts new file mode 100644 index 0000000000..ed3e6d40a6 --- /dev/null +++ b/packages/technical-features/application/electron-main/src/electron/electron-app.test.ts @@ -0,0 +1,17 @@ +import electronAppInjectable from "./electron-app.injectable"; +import { app } from 'electron'; +import { createContainer } from "@ogre-tools/injectable"; +import { applicationFeatureForElectronMain } from "../feature"; +import { registerFeature } from "@k8slens/feature-core"; + +describe('electron-app', () => { + it('is electron app', () => { + const di = createContainer('irrelevant'); + + registerFeature(di, applicationFeatureForElectronMain) + + const actual = di.inject(electronAppInjectable); + + expect(actual).toBe(app); + }); +}); diff --git a/packages/technical-features/application/electron-main/src/feature.ts b/packages/technical-features/application/electron-main/src/feature.ts new file mode 100644 index 0000000000..597d7625f9 --- /dev/null +++ b/packages/technical-features/application/electron-main/src/feature.ts @@ -0,0 +1,22 @@ +import { getFeature } from "@k8slens/feature-core"; +import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration"; +import { applicationFeature } from '@k8slens/application'; + +export const applicationFeatureForElectronMain = getFeature({ + id: "application-for-electron-main", + + register: (di) => { + autoRegister({ + di, + targetModule: module, + + getRequireContexts: () => [ + require.context("./", true, /\.injectable\.(ts|tsx)$/), + ], + }); + }, + + dependencies: [ + applicationFeature + ] +}); diff --git a/packages/technical-features/application/electron-main/src/override-side-effects-with-fakes.ts b/packages/technical-features/application/electron-main/src/override-side-effects-with-fakes.ts new file mode 100644 index 0000000000..0d33c944d8 --- /dev/null +++ b/packages/technical-features/application/electron-main/src/override-side-effects-with-fakes.ts @@ -0,0 +1,6 @@ +import type { DiContainer } from "@ogre-tools/injectable"; +import whenAppIsReadyInjectable from "./start-application/when-app-is-ready.injectable"; + +export const overrideSideEffectsWithFakes = (di: DiContainer) => { + di.override(whenAppIsReadyInjectable, () => () => Promise.resolve()) +}; diff --git a/packages/technical-features/application/electron-main/src/start-application/start-electron-application.injectable.ts b/packages/technical-features/application/electron-main/src/start-application/start-electron-application.injectable.ts new file mode 100644 index 0000000000..5d5944fbaf --- /dev/null +++ b/packages/technical-features/application/electron-main/src/start-application/start-electron-application.injectable.ts @@ -0,0 +1,58 @@ +import { + DiContainer, + getInjectable, + instantiationDecoratorToken, + lifecycleEnum, +} from "@ogre-tools/injectable"; +import { startApplicationInjectionToken } from "@k8slens/application"; +import whenAppIsReadyInjectable from "./when-app-is-ready.injectable"; +import { beforeAnythingInjectionToken } from "./timeslots/before-anything-injection-token"; +import { beforeElectronIsReadyInjectionToken } from "./timeslots/before-electron-is-ready-injection-token"; +import { runManySyncFor } from "@ogre-tools/injectable-utils"; + +const startElectronApplicationInjectable = getInjectable({ + id: "start-electron-application", + + instantiate: () => ({ + decorate: + (toBeDecorated: unknown) => + (di: DiContainer, ...args: unknown[]) => { + const whenAppIsReady = di.inject(whenAppIsReadyInjectable); + const runManySync = runManySyncFor(di); + const beforeAnything = runManySync(beforeAnythingInjectionToken); + const beforeElectronIsReady = runManySync( + beforeElectronIsReadyInjectionToken + ); + + const typedToBeDecorated = toBeDecorated as ( + di: DiContainer, + ...args: unknown[] + ) => unknown; + + const startApplication = typedToBeDecorated(di, ...args) as ( + ...args: unknown[] + ) => unknown; + + return (...startApplicationArgs: unknown[]) => { + beforeAnything(); + beforeElectronIsReady(); + + return (async () => { + await whenAppIsReady(); + + return startApplication(...startApplicationArgs); + })() + }; + }, + + target: startApplicationInjectionToken, + }), + + decorable: false, + + injectionToken: instantiationDecoratorToken, + + lifecycle: lifecycleEnum.singleton, +}); + +export default startElectronApplicationInjectable; diff --git a/packages/technical-features/application/electron-main/src/start-application/timeslots/before-anything-injection-token.ts b/packages/technical-features/application/electron-main/src/start-application/timeslots/before-anything-injection-token.ts new file mode 100644 index 0000000000..f8d2ef9203 --- /dev/null +++ b/packages/technical-features/application/electron-main/src/start-application/timeslots/before-anything-injection-token.ts @@ -0,0 +1,6 @@ +import { getInjectionToken } from "@ogre-tools/injectable"; +import type { Runnable } from "@ogre-tools/injectable-utils"; + +export const beforeAnythingInjectionToken = getInjectionToken({ + id: "before-anything", +}); diff --git a/packages/technical-features/application/electron-main/src/start-application/timeslots/before-electron-is-ready-injection-token.ts b/packages/technical-features/application/electron-main/src/start-application/timeslots/before-electron-is-ready-injection-token.ts new file mode 100644 index 0000000000..c8c88bddae --- /dev/null +++ b/packages/technical-features/application/electron-main/src/start-application/timeslots/before-electron-is-ready-injection-token.ts @@ -0,0 +1,6 @@ +import { getInjectionToken } from "@ogre-tools/injectable"; +import type { Runnable } from "@ogre-tools/injectable-utils"; + +export const beforeElectronIsReadyInjectionToken = getInjectionToken({ + id: "before-electron-is-ready-injection-token", +}); diff --git a/packages/technical-features/application/electron-main/src/start-application/when-app-is-ready.injectable.ts b/packages/technical-features/application/electron-main/src/start-application/when-app-is-ready.injectable.ts new file mode 100644 index 0000000000..27c169b2c2 --- /dev/null +++ b/packages/technical-features/application/electron-main/src/start-application/when-app-is-ready.injectable.ts @@ -0,0 +1,16 @@ +import { getInjectable } from "@ogre-tools/injectable"; +import electronAppInjectable from "../electron/electron-app.injectable"; + +const whenAppIsReadyInjectable = getInjectable({ + id: "when-app-is-ready", + + instantiate: (di) => { + const electronApp = di.inject(electronAppInjectable); + + return () => electronApp.whenReady(); + }, + + decorable: false, +}); + +export default whenAppIsReadyInjectable; diff --git a/packages/technical-features/application/electron-main/src/start-application/when-app-is-ready/when-app-is-ready.test.ts b/packages/technical-features/application/electron-main/src/start-application/when-app-is-ready/when-app-is-ready.test.ts new file mode 100644 index 0000000000..3e3fe40a52 --- /dev/null +++ b/packages/technical-features/application/electron-main/src/start-application/when-app-is-ready/when-app-is-ready.test.ts @@ -0,0 +1,50 @@ +import { createContainer, DiContainer } from "@ogre-tools/injectable"; +import { applicationFeatureForElectronMain } from "../../feature"; +import { registerFeature } from "@k8slens/feature-core"; +import whenAppIsReadyInjectable from "../when-app-is-ready.injectable"; +import { getPromiseStatus } from "@ogre-tools/test-utils"; +import electronAppInjectable from "../../electron/electron-app.injectable"; +import type { AsyncFnMock } from "@async-fn/jest"; +import asyncFn from "@async-fn/jest"; + +describe("when-app-is-ready", () => { + let di: DiContainer; + let whenReadyMock: AsyncFnMock<() => Promise>; + + beforeEach(() => { + di = createContainer("irrelevant"); + + registerFeature(di, applicationFeatureForElectronMain); + + whenReadyMock = asyncFn(); + + di.override( + electronAppInjectable, + () => ({ whenReady: whenReadyMock } as unknown) + ); + }); + + describe("when called", () => { + let actualPromise: Promise; + + beforeEach(() => { + const whenAppIsReady = di.inject(whenAppIsReadyInjectable); + + actualPromise = whenAppIsReady(); + }); + + it("does not resolve yet", async () => { + const promiseStatus = await getPromiseStatus(actualPromise); + + expect(promiseStatus.fulfilled).toBe(false); + }); + + it("when app is ready, resolves", async () => { + await whenReadyMock.resolve(); + + const promiseStatus = await getPromiseStatus(actualPromise); + + expect(promiseStatus.fulfilled).toBe(true); + }); + }); +}); diff --git a/packages/technical-features/application/electron-main/src/starting-of-electron-main-application.test.ts b/packages/technical-features/application/electron-main/src/starting-of-electron-main-application.test.ts new file mode 100644 index 0000000000..fb344a193b --- /dev/null +++ b/packages/technical-features/application/electron-main/src/starting-of-electron-main-application.test.ts @@ -0,0 +1,94 @@ +import { + createContainer, + DiContainer, + getInjectable, +} from "@ogre-tools/injectable"; +import { registerFeature } from "@k8slens/feature-core"; +import { applicationFeatureForElectronMain } from "./feature"; +import { + beforeApplicationIsLoadingInjectionToken, + startApplicationInjectionToken, +} from "@k8slens/application"; +import asyncFn, { AsyncFnMock } from "@async-fn/jest"; +import whenAppIsReadyInjectable from "./start-application/when-app-is-ready.injectable"; +import { beforeAnythingInjectionToken } from "./start-application/timeslots/before-anything-injection-token"; +import { beforeElectronIsReadyInjectionToken } from "./start-application/timeslots/before-electron-is-ready-injection-token"; + +describe("starting-of-electron-main-application", () => { + let di: DiContainer; + let beforeAnythingMock: jest.Mock; + let beforeElectronIsReadyMock: jest.Mock; + let beforeApplicationIsLoadingMock: AsyncFnMock<() => Promise>; + let whenAppIsReadyMock: AsyncFnMock<() => Promise>; + + beforeEach(() => { + di = createContainer("irrelevant"); + + beforeAnythingMock = jest.fn(); + beforeElectronIsReadyMock = jest.fn(); + + beforeApplicationIsLoadingMock = asyncFn(); + whenAppIsReadyMock = asyncFn(); + + registerFeature(di, applicationFeatureForElectronMain); + + const beforeAnythingIsLoadingInjectable = getInjectable({ + id: "before-anything", + instantiate: () => ({ run: beforeAnythingMock }), + injectionToken: beforeAnythingInjectionToken, + }); + + const beforeElectronIsReadyIsLoadingInjectable = getInjectable({ + id: "before-electron-is-ready", + instantiate: () => ({ run: beforeElectronIsReadyMock }), + injectionToken: beforeElectronIsReadyInjectionToken, + }); + + const beforeApplicationIsLoadingInjectable = getInjectable({ + id: "before-application-is-loading", + instantiate: () => ({ run: beforeApplicationIsLoadingMock }), + injectionToken: beforeApplicationIsLoadingInjectionToken, + }); + + di.register( + beforeAnythingIsLoadingInjectable, + beforeElectronIsReadyIsLoadingInjectable, + beforeApplicationIsLoadingInjectable + ); + + di.override(whenAppIsReadyInjectable, () => whenAppIsReadyMock); + }); + + describe("when application is started", () => { + beforeEach(() => { + const startApplication = di.inject(startApplicationInjectionToken); + + startApplication(); + }); + + it("calls for synchronous runnables for before anything", () => { + expect(beforeAnythingMock).toHaveBeenCalled(); + }); + + it("calls for synchronous runnables for before electron is ready", () => { + expect(beforeElectronIsReadyMock).toHaveBeenCalled(); + }); + it("calls to wait when electron is ready", () => { + expect(whenAppIsReadyMock).toHaveBeenCalled(); + }); + + it("does not call runnables for before application is loading yet", () => { + expect(beforeApplicationIsLoadingMock).not.toHaveBeenCalled(); + }); + + describe("when electron is ready", () => { + beforeEach(async () => { + await whenAppIsReadyMock.resolve(); + }); + + it("calls runnables for before application is loading", () => { + expect(beforeApplicationIsLoadingMock).toHaveBeenCalled(); + }); + }); + }); +}); diff --git a/packages/technical-features/application/electron-main/tsconfig.json b/packages/technical-features/application/electron-main/tsconfig.json new file mode 100644 index 0000000000..a4f6fa613e --- /dev/null +++ b/packages/technical-features/application/electron-main/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "@k8slens/typescript/config/base.json" +} diff --git a/packages/technical-features/application/electron-main/webpack.config.js b/packages/technical-features/application/electron-main/webpack.config.js new file mode 100644 index 0000000000..3183f30179 --- /dev/null +++ b/packages/technical-features/application/electron-main/webpack.config.js @@ -0,0 +1 @@ +module.exports = require("@k8slens/webpack").configForNode; diff --git a/packages/technical-features/application/index.ts b/packages/technical-features/application/index.ts deleted file mode 100644 index 8686f83dd1..0000000000 --- a/packages/technical-features/application/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { applicationInformationToken } from "./src/application-information-token"; -export type { ApplicationInformation } from "./src/application-information-token"; - diff --git a/packages/technical-features/feature-core/package.json b/packages/technical-features/feature-core/package.json index 290cfbb327..506e39d773 100644 --- a/packages/technical-features/feature-core/package.json +++ b/packages/technical-features/feature-core/package.json @@ -31,6 +31,6 @@ "test": "jest --coverage --runInBand" }, "peerDependencies": { - "@ogre-tools/injectable": "^15.1.1" + "@ogre-tools/injectable": "^15.1.2" } }