Allow to import app as a library (#6722)

* unify build fs layout

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* use currentApp path for static files

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* lint fix

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* allow to import open-lens

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* allow to customize both main & renderer

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix compile-library script

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* remove bundled extensions

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* similar interface for both main & renderer

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* use startApp on both sides

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix startApp import

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix startApp import

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* Fix injection cycle (somehow)

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* use cwd in download_binaries

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* introduce applicationInformationToken

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* register applicationInformationInjectable in main & renderer

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* allow to define bundled extensions via appStart

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* compile node-fetch automatically via prepare

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* define peerDependencies

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* webpack fixes

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* rename application-information-token.injectable.ts -> application-information-token.ts

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* monaco-editor as externals

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* refactor application-information

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* introduce bundledExtensionInjectionToken

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* mark library exports as experimental

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* move extension npm package files & add release automation

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* add missing build files to package

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix bad merge conflict resolve

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix package.json name

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* allow to set mode via startApp

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* revert unnecessary changes

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* webpack: fix extensionOutDir

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* remove unnecessary peerDependencies

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* introduce nodeEnvInjectionToken

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* remove NODE_ENV from environmentVariablesInjectable

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix jest modulePathIgnorePatterns

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix duplicate injectable registration

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

* fix build executableName

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
Signed-off-by: Sebastian Malton <sebastian@malton.name>
Co-authored-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Jari KolehmainenandSebastian Malton authored and GitHub committed 2022-12-23 13:33:35 +02:00
1 parent ba908c860d
commit 97551bb7f0
57 files changed
+712 -263

No files matched your search

@@ -6,7 +6,7 @@
// Fix embedded kubeconfig paths under snap config
import { getInjectable } from "@ogre-tools/injectable";
import applicationInformationInjectable from "../../../common/vars/application-information.injectable";
import applicationInformationToken from "../../../common/vars/application-information-token";
import { clusterStoreMigrationInjectionToken } from "../../../common/cluster-store/migration-token";
import loggerInjectable from "../../../common/logger.injectable";
import isSnapPackageInjectable from "../../../common/vars/is-snap-package.injectable";
@@ -16,7 +16,7 @@ import pathExistsSyncInjectable from "../../../common/fs/path-exists-sync.inject
const clusterStoreSnapMigrationInjectable = getInjectable({
id: "cluster-store-snap-migration",
instantiate: (di) => {
const { version } = di.inject(applicationInformationInjectable);
const { version } = di.inject(applicationInformationToken);
const logger = di.inject(loggerInjectable);
const isSnapPackage = di.inject(isSnapPackageInjectable);
const pathExistsSync = di.inject(pathExistsSyncInjectable);
+36
View File
@@ -0,0 +1,36 @@
/**
* 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 { getInjectable } from "@ogre-tools/injectable";
import { runInAction } from "mobx";
import nodeEnvInjectionToken from "../common/vars/node-env-injection-token";
import { registerInjectables } from "./register-injectables";
import startMainApplicationInjectable from "./start-main-application/start-main-application.injectable";
interface AppConfig {
di: DiContainer;
mode: string;
}
export function createApp(conf: AppConfig) {
const { di, mode } = conf;
runInAction(() => {
di.register(getInjectable({
id: "node-env",
instantiate: () => mode,
injectionToken: nodeEnvInjectionToken,
}));
registerInjectables(di);
});
const startMainApplication = di.inject(startMainApplicationInjectable);
return {
start: () => startMainApplication(),
};
}
@@ -3,6 +3,7 @@
* 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 loggerInjectable from "../../../common/logger.injectable";
import { onLoadOfApplicationInjectionToken } from "../../start-main-application/runnable-tokens/on-load-of-application-injection-token";
@@ -11,11 +12,12 @@ const setupDeveloperToolsInDevelopmentEnvironmentInjectable = getInjectable({
instantiate: (di) => {
const logger = di.inject(loggerInjectable);
const nodeEnv = di.inject(nodeEnvInjectionToken);
return {
id: "setup-developer-tools-in-development-environment",
run: () => {
if (process.env.NODE_ENV !== "development") {
if (nodeEnv !== "development") {
return;
}
+26
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 * as Mobx from "mobx";
import { spawn } from "node-pty";
import * as LensExtensionsCommonApi from "../extensions/common-api";
import * as LensExtensionsMainApi from "../extensions/main-api";
/**
* Exports for virtual package "@k8slens/extensions" for main-process.
* All exporting names available in global runtime scope:
* e.g. global.Mobx, global.LensExtensions
*/
const LensExtensions = {
Common: LensExtensionsCommonApi,
Main: LensExtensionsMainApi,
};
const Pty = {
spawn,
};
export { Mobx, LensExtensions, Pty };
+2 -16
View File
@@ -3,28 +3,14 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { createContainer } from "@ogre-tools/injectable";
import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration";
import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx";
import { runInAction } from "mobx";
import { Environments, setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
import applicationInformationInjectable from "../common/vars/application-information-injectable";
export const getDi = () => {
const di = createContainer("main");
setLegacyGlobalDiForExtensionApi(di, Environments.main);
runInAction(() => {
registerMobX(di);
autoRegister({
di,
requireContexts: [
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("../features", true, CONTEXT_MATCHER_FOR_FEATURES),
],
});
di.register(applicationInformationInjectable);
});
return di;
+10 -1
View File
@@ -5,7 +5,7 @@
import { kebabCase, noop, chunk } from "lodash/fp";
import type { DiContainer, Injectable } from "@ogre-tools/injectable";
import { createContainer, isInjectable } from "@ogre-tools/injectable";
import { createContainer, isInjectable, getInjectable } from "@ogre-tools/injectable";
import { Environments, setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
import writeJsonFileInjectable from "../common/fs/write-json-file.injectable";
import readJsonFileInjectable from "../common/fs/read-json-file.injectable";
@@ -71,6 +71,8 @@ import kubectlDownloadingNormalizedArchInjectable from "./kubectl/normalized-arc
import initializeClusterManagerInjectable from "./cluster/initialize-manager.injectable";
import addKubeconfigSyncAsEntitySourceInjectable from "./start-main-application/runnables/kube-config-sync/add-source.injectable";
import type { GlobalOverride } from "../common/test-utils/get-global-override";
import applicationInformationInjectable from "../common/vars/application-information-injectable";
import nodeEnvInjectionToken from "../common/vars/node-env-injection-token";
export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) {
const {
@@ -79,6 +81,12 @@ export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {})
const di = createContainer("main");
di.register(getInjectable({
id: "node-env",
instantiate: () => "test",
injectionToken: nodeEnvInjectionToken,
}));
setLegacyGlobalDiForExtensionApi(di, Environments.main);
di.preventSideEffects();
@@ -93,6 +101,7 @@ export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {})
runInAction(() => {
registerMobX(di);
di.register(applicationInformationInjectable);
chunk(100)(injectables).forEach(chunkInjectables => {
di.register(...chunkInjectables);
+10 -29
View File
@@ -5,38 +5,19 @@
// Main process
import * as Mobx from "mobx";
import { spawn } from "node-pty";
import process from "process";
import * as LensExtensionsCommonApi from "../extensions/common-api";
import * as LensExtensionsMainApi from "../extensions/main-api";
import { getDi } from "./getDi";
import startMainApplicationInjectable from "./start-main-application/start-main-application.injectable";
import { Mobx, LensExtensions, Pty } from "./extension-api";
import { createApp } from "./create-app";
const di = getDi();
const startMainApplication = di.inject(startMainApplicationInjectable);
const app = createApp({
di,
mode: process.env.NODE_ENV || "development",
});
(async () => {
try {
await startMainApplication();
} catch (error) {
console.error(error);
process.exit(1);
}
})();
/**
* Exports for virtual package "@k8slens/extensions" for main-process.
* All exporting names available in global runtime scope:
* e.g. global.Mobx, global.LensExtensions
*/
const LensExtensions = {
Common: LensExtensionsCommonApi,
Main: LensExtensionsMainApi,
};
const Pty = {
spawn,
};
app.start().catch((error) => {
console.error(error);
process.exit(1);
});
export { Mobx, LensExtensions, Pty };
+21
View File
@@ -0,0 +1,21 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { afterApplicationIsLoadedInjectionToken } from "./start-main-application/runnable-tokens/after-application-is-loaded-injection-token";
import { beforeApplicationIsLoadingInjectionToken } from "./start-main-application/runnable-tokens/before-application-is-loading-injection-token";
import { beforeElectronIsReadyInjectionToken } from "./start-main-application/runnable-tokens/before-electron-is-ready-injection-token";
import { onLoadOfApplicationInjectionToken } from "./start-main-application/runnable-tokens/on-load-of-application-injection-token";
import * as extensionApi from "./extension-api";
import { createApp } from "./create-app";
// @experimental
export {
createApp,
extensionApi,
afterApplicationIsLoadedInjectionToken,
beforeApplicationIsLoadingInjectionToken,
beforeElectronIsReadyInjectionToken,
onLoadOfApplicationInjectionToken,
};
+29
View File
@@ -0,0 +1,29 @@
/**
* 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 { registerMobX } from "@ogre-tools/injectable-extension-for-mobx";
import { runInAction } from "mobx";
import { Environments, setLegacyGlobalDiForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
export function registerInjectables(di: DiContainer) {
setLegacyGlobalDiForExtensionApi(di, Environments.main);
runInAction(() => {
registerMobX(di);
autoRegister({
di,
requireContexts: [
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("../features", true, CONTEXT_MATCHER_FOR_FEATURES),
],
});
});
return di;
}
@@ -6,19 +6,17 @@ import { getInjectable } from "@ogre-tools/injectable";
import httpProxy from "http-proxy";
import { webpackDevServerPort } from "../../../../webpack/vars";
import { publicPath } from "../../../common/vars";
import appNameInjectable from "../../../common/vars/app-name.injectable";
import type { LensApiRequest, RouteResponse } from "../../router/route";
const devStaticFileRouteHandlerInjectable = getInjectable({
id: "dev-static-file-route-handler",
instantiate: (di) => {
instantiate: () => {
const proxy = httpProxy.createProxy();
const appName = di.inject(appNameInjectable);
const proxyTarget = `http://127.0.0.1:${webpackDevServerPort}`;
return async ({ raw: { req, res }}: LensApiRequest<"/{path*}">): Promise<RouteResponse<Buffer>> => {
if (req.url === "/" || !req.url) {
req.url = `${publicPath}/${appName}.html`;
req.url = `${publicPath}/index.html`;
} else if (!req.url.startsWith("/build/")) {
return { statusCode: 404 };
}
@@ -6,7 +6,6 @@ import { getInjectable } from "@ogre-tools/injectable";
import readFileBufferInjectable from "../../../common/fs/read-file-buffer.injectable";
import joinPathsInjectable from "../../../common/path/join-paths.injectable";
import staticFilesDirectoryInjectable from "../../../common/vars/static-files-directory.injectable";
import appNameInjectable from "../../../common/vars/app-name.injectable";
import type { LensApiRequest } from "../../router/route";
import path from "path";
import type { SupportedFileExtension } from "../../router/router-content-types";
@@ -20,7 +19,6 @@ const prodStaticFileRouteHandlerInjectable = getInjectable({
const readFileBuffer = di.inject(readFileBufferInjectable);
const joinPaths = di.inject(joinPathsInjectable);
const staticFilesDirectory = di.inject(staticFilesDirectoryInjectable);
const appName = di.inject(appNameInjectable);
const logger = di.inject(loggerInjectable);
return async ({ params }: LensApiRequest<"/{path*}">) => {
@@ -49,7 +47,7 @@ const prodStaticFileRouteHandlerInjectable = getInjectable({
return { statusCode: 404 };
}
filePath = `${publicPath}/${appName}.html`;
filePath = `${publicPath}/index.html`;
}
}
@@ -12,7 +12,7 @@ import openLinkInBrowserInjectable from "../../../../common/utils/open-link-in-b
import getAbsolutePathInjectable from "../../../../common/path/get-absolute-path.injectable";
import lensResourcesDirInjectable from "../../../../common/vars/lens-resources-dir.injectable";
import isLinuxInjectable from "../../../../common/vars/is-linux.injectable";
import applicationInformationInjectable from "../../../../common/vars/application-information.injectable";
import applicationInformationToken from "../../../../common/vars/application-information-token";
import pathExistsSyncInjectable from "../../../../common/fs/path-exists-sync.injectable";
@@ -54,7 +54,7 @@ const createElectronWindowInjectable = getInjectable({
const getAbsolutePath = di.inject(getAbsolutePathInjectable);
const lensResourcesDir = di.inject(lensResourcesDirInjectable);
const isLinux = di.inject(isLinuxInjectable);
const applicationInformation = di.inject(applicationInformationInjectable);
const applicationInformation = di.inject(applicationInformationToken);
const pathExistsSync = di.inject(pathExistsSyncInjectable);
return (configuration) => {
@@ -0,0 +1,24 @@
/**
* 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 applicationInformationInjectable from "../../common/vars/application-information-injectable";
export default getGlobalOverride(applicationInformationInjectable, () => ({
name: "some-product-name",
productName: "some-product-name",
version: "6.0.0",
build: {} as any,
config: {
k8sProxyVersion: "0.2.1",
bundledKubectlVersion: "1.23.3",
bundledHelmVersion: "3.7.2",
sentryDsn: "",
contentSecurityPolicy: "script-src 'unsafe-eval' 'self'; frame-src http://*.localhost:*/; img-src * data:",
welcomeRoute: "/welcome",
},
copyright: "some-copyright-information",
description: "some-descriptive-text",
}));
@@ -7,13 +7,13 @@ import { docsUrl, slackUrl } from "../../../common/vars";
import type { WeblinkData } from "../../../common/weblinks-store/weblink-store";
import { getInjectable } from "@ogre-tools/injectable";
import { weblinkStoreMigrationInjectionToken } from "../../../common/weblinks-store/migration-token";
import applicationInformationInjectable from "../../../common/vars/application-information.injectable";
import applicationInformationToken from "../../../common/vars/application-information-token";
import { lensDocumentationWeblinkId, lensSlackWeblinkId } from "../links";
const currentVersionWeblinkStoreMigrationInjectable = getInjectable({
id: "current-version-weblink-store-migration",
instantiate: (di) => {
const { version } = di.inject(applicationInformationInjectable);
const { version } = di.inject(applicationInformationToken);
return {
version, // Run always after upgrade