1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Consolidate more bootstrapping into startFrame

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-12-05 09:58:29 -05:00
parent 01d3914b5a
commit 9e1d182459
10 changed files with 281 additions and 40 deletions

View File

@ -0,0 +1,23 @@
/**
* 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 { setAutoFreeze, enableMapSet } from "immer";
import { evenBeforeFrameStartsInjectionToken } from "../tokens";
const configureImmerInjectable = getInjectable({
id: "configure-immer",
instantiate: () => ({
id: "configure-immer",
run: () => {
// Docs: https://immerjs.github.io/immer/
// Required in `utils/storage-helper.ts`
setAutoFreeze(false); // allow to merge mobx observables
enableMapSet(); // allow to merge maps and sets
},
}),
injectionToken: evenBeforeFrameStartsInjectionToken,
});
export default configureImmerInjectable;

View File

@ -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 { configure } from "mobx";
import { evenBeforeFrameStartsInjectionToken } from "../tokens";
const configureMobxInjectable = getInjectable({
id: "configure-mobx",
instantiate: () => ({
id: "configure-mobx",
run: () => {
// Docs: https://mobx.js.org/configuration.html
configure({
enforceActions: "never",
// TODO: enable later (read more: https://mobx.js.org/migrating-from-4-or-5.html)
// computedRequiresReaction: true,
// reactionRequiresObservable: true,
// observableRequiresReaction: true,
});
},
}),
injectionToken: evenBeforeFrameStartsInjectionToken,
});
export default configureMobxInjectable;

View File

@ -0,0 +1,26 @@
/**
* 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 { customMonacoThemeInjectionToken } from "../../components/monaco-editor";
import addNewMonacoThemeInjectable from "../../monaco/add-new-theme.injectable";
import { evenBeforeFrameStartsInjectionToken } from "../tokens";
const loadMonacoThemesInjectable = getInjectable({
id: "load-monaco-themes",
instantiate: (di) => {
const customThemes = di.injectMany(customMonacoThemeInjectionToken);
const addNewMonacoTheme = di.inject(addNewMonacoThemeInjectable);
return {
id: "load-monaco-themes",
run: () => {
customThemes.forEach(addNewMonacoTheme);
},
};
},
injectionToken: evenBeforeFrameStartsInjectionToken,
});
export default loadMonacoThemesInjectable;

View File

@ -0,0 +1,84 @@
/**
* 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 autoRegistrationEmitterInjectable from "../../../common/k8s-api/api-manager/auto-registration-emitter.injectable";
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
import { CustomResourceStore } from "../../../common/k8s-api/api-manager/resource.store";
import type { CustomResourceDefinition } from "../../../common/k8s-api/endpoints";
import { KubeApi } from "../../../common/k8s-api/kube-api";
import { KubeObject } from "../../../common/k8s-api/kube-object";
import type { KubeObjectStoreDependencies } from "../../../common/k8s-api/kube-object.store";
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
import { evenBeforeClusterFrameStartsInjectionToken } from "../tokens";
const setupAutoRegistrationInjectable = getInjectable({
id: "setup-auto-registration",
instantiate: (di) => ({
id: "setup-auto-registration",
run: () => {
const autoRegistrationEmitter = di.inject(autoRegistrationEmitterInjectable);
const beforeApiManagerInitializationCrds: CustomResourceDefinition[] = [];
const beforeApiManagerInitializationApis: KubeApi[] = [];
const deps: KubeObjectStoreDependencies = {
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
};
let initialized = false;
const autoInitCustomResourceStore = (crd: CustomResourceDefinition) => {
const objectConstructor = class extends KubeObject {
static readonly kind = crd.getResourceKind();
static readonly namespaced = crd.isNamespaced();
static readonly apiBase = crd.getResourceApiBase();
};
const api = (() => {
const rawApi = apiManager.getApi(objectConstructor.apiBase);
if (rawApi) {
return rawApi;
}
const api = new KubeApi({ objectConstructor });
apiManager.registerApi(api);
return api;
})();
if (!apiManager.getStore(api)) {
apiManager.registerStore(new CustomResourceStore(deps, api));
}
};
const autoInitKubeApi = (api: KubeApi) => {
apiManager.registerApi(api);
};
autoRegistrationEmitter
.on("customResourceDefinition", (crd) => {
if (initialized) {
autoInitCustomResourceStore(crd);
} else {
beforeApiManagerInitializationCrds.push(crd);
}
})
.on("kubeApi", (api) => {
if (initialized) {
autoInitKubeApi(api);
} else {
beforeApiManagerInitializationApis.push(api);
}
});
const apiManager = di.inject(apiManagerInjectable);
beforeApiManagerInitializationCrds.forEach(autoInitCustomResourceStore);
beforeApiManagerInitializationApis.forEach(autoInitKubeApi);
initialized = true;
},
}),
injectionToken: evenBeforeClusterFrameStartsInjectionToken,
});
export default setupAutoRegistrationInjectable;

View File

@ -0,0 +1,34 @@
/**
* 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 { reaction } from "mobx";
import { currentClusterMessageChannel } from "../../../common/cluster/current-cluster-channel";
import { sendMessageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
import matchedClusterIdInjectable from "../../navigation/matched-cluster-id.injectable";
import { evenBeforeMainFrameStartsInjectionToken } from "../tokens";
const setupCurrentClusterBroadcastInjectable = getInjectable({
id: "setup-current-cluster-broadcast",
instantiate: (di) => {
const matchedClusterId = di.inject(matchedClusterIdInjectable);
const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken);
return {
id: "setup-current-cluster-broadcast",
run: () => {
reaction(
() => matchedClusterId.get(),
clusterId => sendMessageToChannel(currentClusterMessageChannel, clusterId),
{
fireImmediately: true,
},
);
},
};
},
injectionToken: evenBeforeMainFrameStartsInjectionToken,
});
export default setupCurrentClusterBroadcastInjectable;

View File

@ -0,0 +1,26 @@
/**
* 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 isMacInjectable from "../../../common/vars/is-mac.injectable";
import { beforeFrameStartsInjectionToken } from "../tokens";
const setupRootMacClassnameInjectable = getInjectable({
id: "setup-root-mac-classname",
instantiate: (di) => {
const isMac = di.inject(isMacInjectable);
return {
id: "setup-root-mac-classname",
run: () => {
const rootElem = document.getElementById("app");
rootElem?.classList.toggle("is-mac", isMac);
},
};
},
injectionToken: beforeFrameStartsInjectionToken,
});
export default setupRootMacClassnameInjectable;

View File

@ -0,0 +1,25 @@
/**
* 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 initializeSentryReportingWithInjectable from "../../../common/error-reporting/initialize-sentry-reporting.injectable";
import { evenBeforeMainFrameStartsInjectionToken } from "../tokens";
import { init } from "@sentry/electron/renderer";
const setupSentryInjectable = getInjectable({
id: "setup-sentry",
instantiate: (di) => {
const initializeSentryReportingWith = di.inject(initializeSentryReportingWithInjectable);
return {
id: "setup-sentry",
run: () => {
initializeSentryReportingWith(init);
},
};
},
injectionToken: evenBeforeMainFrameStartsInjectionToken,
});
export default setupSentryInjectable;

View File

@ -0,0 +1,25 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectionToken } from "@ogre-tools/injectable";
import type { Runnable } from "../../common/runnable/run-many-for";
export const evenBeforeFrameStartsInjectionToken = getInjectionToken<Runnable>({
id: "even-before-frame-starts",
});
// NOTE: these are only run when process.isMainFrame === true
export const evenBeforeMainFrameStartsInjectionToken = getInjectionToken<Runnable>({
id: "even-before-main-frame-starts",
});
// NOTE: these are only run when process.isMainFrame === false
export const evenBeforeClusterFrameStartsInjectionToken = getInjectionToken<Runnable>({
id: "even-before-cluster-frame-starts",
});
export const beforeFrameStartsInjectionToken = getInjectionToken<Runnable>({
id: "before-frame-starts",
});

View File

@ -13,13 +13,8 @@ import * as ReactRouter from "react-router";
import * as ReactRouterDom from "react-router-dom";
import * as LensExtensionsCommonApi from "../extensions/common-api";
import * as LensExtensionsRendererApi from "../extensions/renderer-api";
import { delay } from "../common/utils";
import { isMac, isDevelopment } from "../common/vars";
import { DefaultProps } from "./mui-base-theme";
import configurePackages from "../common/configure-packages";
import * as initializers from "./initializers";
import logger from "../common/logger";
import { registerCustomThemes } from "./components/monaco-editor";
import { getDi } from "./getDi";
import { DiContextProvider } from "@ogre-tools/injectable-react";
import type { DiContainer } from "@ogre-tools/injectable";
@ -36,60 +31,32 @@ import themeStoreInjectable from "./themes/store.injectable";
import navigateToAddClusterInjectable from "../common/front-end-routing/routes/add-cluster/navigate-to-add-cluster.injectable";
import addSyncEntriesInjectable from "./initializers/add-sync-entries.injectable";
import hotbarStoreInjectable from "../common/hotbars/store.injectable";
import { bindEvents } from "./navigation/events";
import openDeleteClusterDialogInjectable from "./components/delete-cluster-dialog/open.injectable";
import kubernetesClusterCategoryInjectable from "../common/catalog/categories/kubernetes-cluster.injectable";
import autoRegistrationInjectable from "../common/k8s-api/api-manager/auto-registration.injectable";
import assert from "assert";
import startFrameInjectable from "./start-frame/start-frame.injectable";
configurePackages(); // global packages
registerCustomThemes(); // monaco editor themes
/**
* If this is a development build, wait a second to attach
* Chrome Debugger to renderer process
* https://stackoverflow.com/questions/52844870/debugging-electron-renderer-process-with-vscode
*/
async function attachChromeDebugger() {
if (isDevelopment) {
await delay(1000);
}
}
import loggerInjectable from "../common/logger.injectable";
import isLinuxInjectable from "../common/vars/is-linux.injectable";
import isWindowsInjectable from "../common/vars/is-windows.injectable";
export async function bootstrap(di: DiContainer) {
const startFrame = di.inject(startFrameInjectable);
const logger = di.inject(loggerInjectable);
await startFrame();
// TODO: Consolidate import time side-effect to setup time
bindEvents();
const rootElem = document.getElementById("app");
const logPrefix = `[BOOTSTRAP-${process.isMainFrame ? "ROOT" : "CLUSTER"}-FRAME]:`;
assert(rootElem, "#app MUST exist");
/**
* This is injected here to initialize it for the side effect.
*
* The side effect CANNOT be within `apiManagerInjectable` itself since that causes circular
* dependencies with the current need for legacy di use.
*
* This also MUST be done before anything else so that it can start listening for the events for
* auto initialization.
*/
di.inject(autoRegistrationInjectable);
await attachChromeDebugger();
rootElem.classList.toggle("is-mac", isMac);
logger.info(`${logPrefix} initializing CatalogCategoryRegistryEntries`);
initializers.initCatalogCategoryRegistryEntries({
navigateToAddCluster: di.inject(navigateToAddClusterInjectable),
addSyncEntries: di.inject(addSyncEntriesInjectable),
kubernetesClusterCategory: di.inject(kubernetesClusterCategoryInjectable),
isLinux: di.inject(isLinuxInjectable),
isWindows: di.inject(isWindowsInjectable),
});
logger.info(`${logPrefix} initializing Catalog`);

View File

@ -4,19 +4,22 @@
*/
import type { KubernetesClusterCategory } from "../../common/catalog-entities";
import { isLinux, isWindows } from "../../common/vars";
import { PathPicker } from "../components/path-picker";
interface Dependencies {
navigateToAddCluster: () => void;
addSyncEntries: (filePaths: string[]) => void;
kubernetesClusterCategory: KubernetesClusterCategory;
isWindows: boolean;
isLinux: boolean;
}
export function initCatalogCategoryRegistryEntries({
navigateToAddCluster,
addSyncEntries,
kubernetesClusterCategory,
isWindows,
isLinux,
} : Dependencies) {
kubernetesClusterCategory.on("catalogAddMenu", ctx => {
ctx.menuItems.push(