mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Merge branch 'master' into enhancement-ability-to-remove-subnamespaces
This commit is contained in:
136 files changed
+2940
-1256
No files matched your search
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
const { notarize } = require("electron-notarize");
|
||||
|
||||
exports.default = async function notarizing(context) {
|
||||
const { electronPlatformName, appOutDir } = context;
|
||||
|
||||
if (electronPlatformName !== "darwin") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!process.env.APPLEID || !process.env.APPLEIDPASS) {
|
||||
return;
|
||||
}
|
||||
|
||||
const appName = context.packager.appInfo.productFilename;
|
||||
|
||||
return await notarize({
|
||||
appBundleId: process.env.APPBUNDLEID || "io.kontena.lens-app",
|
||||
appPath: `${appOutDir}/${appName}.app`,
|
||||
appleId: process.env.APPLEID,
|
||||
appleIdPassword: process.env.APPLEIDPASS,
|
||||
ascProvider:process.env.ASCPROVIDER,
|
||||
});
|
||||
};
|
||||
@@ -57,7 +57,7 @@
|
||||
"test:unit": "jest --testPathIgnorePatterns integration",
|
||||
"test:watch": "func() { jest ${1} --watch --testPathIgnorePatterns integration; }; func",
|
||||
"lint": "PROD=true eslint --ext js,ts,tsx --max-warnings=0 .",
|
||||
"lint:fix": "npm run lint --fix"
|
||||
"lint:fix": "npm run lint -- --fix"
|
||||
},
|
||||
"config": {
|
||||
"k8sProxyVersion": "0.3.0",
|
||||
@@ -130,11 +130,11 @@
|
||||
"@k8slens/node-fetch": "^6.4.0-beta.13",
|
||||
"@kubernetes/client-node": "^0.18.1",
|
||||
"@material-ui/styles": "^4.11.5",
|
||||
"@ogre-tools/fp": "^12.0.1",
|
||||
"@ogre-tools/injectable": "^12.0.1",
|
||||
"@ogre-tools/injectable-extension-for-auto-registration": "^12.0.1",
|
||||
"@ogre-tools/injectable-extension-for-mobx": "^12.0.1",
|
||||
"@ogre-tools/injectable-react": "^12.0.1",
|
||||
"@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",
|
||||
"@sentry/electron": "^3.0.8",
|
||||
"@sentry/integrations": "^6.19.3",
|
||||
"@side/jest-runtime": "^1.1.0",
|
||||
@@ -268,7 +268,6 @@
|
||||
"dompurify": "^2.4.4",
|
||||
"electron": "^19.1.9",
|
||||
"electron-builder": "^23.6.0",
|
||||
"electron-notarize": "^0.3.0",
|
||||
"esbuild": "^0.17.8",
|
||||
"esbuild-loader": "^2.21.0",
|
||||
"eslint": "^8.33.0",
|
||||
@@ -330,6 +329,7 @@
|
||||
"xterm-addon-fit": "^0.5.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@k8slens/application": "^6.4.0-beta.13",
|
||||
"@types/byline": "^4.2.33",
|
||||
"@types/chart.js": "^2.9.36",
|
||||
"@types/color": "^3.0.3",
|
||||
|
||||
@@ -74,8 +74,7 @@ describe("cluster-store", () => {
|
||||
di.override(kubectlBinaryNameInjectable, () => "kubectl");
|
||||
di.override(kubectlDownloadingNormalizedArchInjectable, () => "amd64");
|
||||
di.override(normalizedPlatformInjectable, () => "darwin");
|
||||
createCluster = di.inject(createClusterInjectionToken);
|
||||
getCustomKubeConfigFilePath = di.inject(getCustomKubeConfigFilePathInjectable);
|
||||
|
||||
writeJsonSync = di.inject(writeJsonSyncInjectable);
|
||||
writeFileSync = di.inject(writeFileSyncInjectable);
|
||||
writeBufferSync = di.inject(writeBufferSyncInjectable);
|
||||
@@ -85,6 +84,9 @@ describe("cluster-store", () => {
|
||||
|
||||
describe("empty config", () => {
|
||||
beforeEach(async () => {
|
||||
createCluster = di.inject(createClusterInjectionToken);
|
||||
getCustomKubeConfigFilePath = di.inject(getCustomKubeConfigFilePathInjectable);
|
||||
|
||||
writeJsonSync("/some-directory-for-user-data/lens-cluster-store.json", {});
|
||||
clusterStore = di.inject(clusterStoreInjectable);
|
||||
clusterStore.load();
|
||||
@@ -198,6 +200,10 @@ describe("cluster-store", () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
createCluster = di.inject(createClusterInjectionToken);
|
||||
getCustomKubeConfigFilePath = di.inject(getCustomKubeConfigFilePathInjectable);
|
||||
|
||||
clusterStore = di.inject(clusterStoreInjectable);
|
||||
clusterStore.load();
|
||||
});
|
||||
@@ -249,6 +255,10 @@ describe("cluster-store", () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
createCluster = di.inject(createClusterInjectionToken);
|
||||
getCustomKubeConfigFilePath = di.inject(getCustomKubeConfigFilePathInjectable);
|
||||
|
||||
clusterStore = di.inject(clusterStoreInjectable);
|
||||
clusterStore.load();
|
||||
});
|
||||
@@ -262,6 +272,11 @@ describe("cluster-store", () => {
|
||||
|
||||
describe("pre 3.6.0-beta.1 config with an existing cluster", () => {
|
||||
beforeEach(() => {
|
||||
di.override(storeMigrationVersionInjectable, () => "3.6.0");
|
||||
|
||||
createCluster = di.inject(createClusterInjectionToken);
|
||||
getCustomKubeConfigFilePath = di.inject(getCustomKubeConfigFilePathInjectable);
|
||||
|
||||
writeJsonSync("/some-directory-for-user-data/lens-cluster-store.json", {
|
||||
__internal__: {
|
||||
migrations: {
|
||||
@@ -281,7 +296,6 @@ describe("cluster-store", () => {
|
||||
});
|
||||
writeBufferSync("/some-directory-for-user-data/icon_path", testDataIcon);
|
||||
|
||||
di.override(storeMigrationVersionInjectable, () => "3.6.0");
|
||||
|
||||
clusterStore = di.inject(clusterStoreInjectable);
|
||||
clusterStore.load();
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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 kubectlApplyAllInjectable from "../../main/kubectl/kubectl-apply-all.injectable";
|
||||
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
|
||||
import type { KubernetesCluster } from "../catalog-entities";
|
||||
import readDirectoryInjectable from "../fs/read-directory.injectable";
|
||||
import readFileInjectable from "../fs/read-file.injectable";
|
||||
import createResourceStackInjectable from "../k8s/create-resource-stack.injectable";
|
||||
import appPathsStateInjectable from "../app-paths/app-paths-state.injectable";
|
||||
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
|
||||
describe("create resource stack tests", () => {
|
||||
let di: DiContainer;
|
||||
let cluster: KubernetesCluster;
|
||||
|
||||
beforeEach(async () => {
|
||||
di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
cluster = {
|
||||
getId: () => "test-cluster",
|
||||
} as any;
|
||||
|
||||
di.override(readDirectoryInjectable, () => () => Promise.resolve(["file1"]) as any);
|
||||
di.override(readFileInjectable, () => () => Promise.resolve("filecontents"));
|
||||
di.override(appPathsStateInjectable, () => ({
|
||||
get: () => ({}),
|
||||
}));
|
||||
di.override(directoryForUserDataInjectable, () => "/some-directory-for-user-data");
|
||||
|
||||
});
|
||||
|
||||
describe("kubectlApplyFolder", () => {
|
||||
it("returns response", async () => {
|
||||
di.override(kubectlApplyAllInjectable, () => () => Promise.resolve({
|
||||
callWasSuccessful: true as const,
|
||||
response: "success",
|
||||
}));
|
||||
|
||||
const createResourceStack = di.inject(createResourceStackInjectable);
|
||||
const resourceStack = createResourceStack(cluster, "test");
|
||||
|
||||
const response = await resourceStack.kubectlApplyFolder("/foo/bar");
|
||||
|
||||
expect(response).toEqual("success");
|
||||
});
|
||||
|
||||
it("throws on error", async () => {
|
||||
di.override(kubectlApplyAllInjectable, () => () => Promise.resolve({
|
||||
callWasSuccessful: false as const,
|
||||
error: "No permissions",
|
||||
}));
|
||||
|
||||
const createResourceStack = di.inject(createResourceStackInjectable);
|
||||
const resourceStack = createResourceStack(cluster, "test");
|
||||
|
||||
await expect(() => resourceStack.kubectlApplyFolder("/foo/bar")).rejects.toThrow("No permissions");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -30,9 +30,9 @@ describe("user store tests", () => {
|
||||
get: () => "latest" as const,
|
||||
init: async () => {},
|
||||
}));
|
||||
|
||||
await di.inject(defaultUpdateChannelInjectable).init();
|
||||
|
||||
userStore = di.inject(userStoreInjectable);
|
||||
});
|
||||
|
||||
describe("for an empty config", () => {
|
||||
@@ -42,6 +42,8 @@ describe("user store tests", () => {
|
||||
writeJsonSync("/some-directory-for-user-data/lens-user-store.json", {});
|
||||
writeJsonSync("/some-directory-for-user-data/kube_config", {});
|
||||
|
||||
userStore = di.inject(userStoreInjectable);
|
||||
|
||||
userStore.load();
|
||||
});
|
||||
|
||||
@@ -90,6 +92,8 @@ describe("user store tests", () => {
|
||||
|
||||
di.override(storeMigrationVersionInjectable, () => "10.0.0");
|
||||
|
||||
userStore = di.inject(userStoreInjectable);
|
||||
|
||||
userStore.load();
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { Environments, getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
import { getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
import type { CatalogEntityContextMenuContext, CatalogEntityMetadata, CatalogEntityStatus } from "../catalog";
|
||||
import { CatalogCategory, CatalogEntity, categoryVersion } from "../catalog/catalog-entity";
|
||||
import productNameInjectable from "../vars/product-name.injectable";
|
||||
@@ -32,7 +32,7 @@ export class WebLink extends CatalogEntity<CatalogEntityMetadata, WebLinkStatus,
|
||||
|
||||
onContextMenuOpen(context: CatalogEntityContextMenuContext) {
|
||||
// NOTE: this is safe because `onContextMenuOpen` is only supposed to be called in the renderer
|
||||
const di = getEnvironmentSpecificLegacyGlobalDiForExtensionApi(Environments.renderer);
|
||||
const di = getEnvironmentSpecificLegacyGlobalDiForExtensionApi("renderer");
|
||||
const productName = di.inject(productNameInjectable);
|
||||
const weblinkStore = di.inject(weblinkStoreInjectable);
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* 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<void>;
|
||||
readonly di: DiContainerForInjection;
|
||||
}
|
||||
|
||||
export type CreateApplication = (config: ApplicationConfig) => Application;
|
||||
+2
-2
@@ -2,13 +2,13 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { applicationInformationToken } from "@k8slens/application";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { applicationInformationToken } from "../../../vars/application-information-token";
|
||||
|
||||
const welcomeRouteConfigInjectable = getInjectable({
|
||||
id: "welcome-route-config",
|
||||
|
||||
instantiate: (di) => di.inject(applicationInformationToken).config.welcomeRoute,
|
||||
instantiate: (di) => di.inject(applicationInformationToken).welcomeRoute,
|
||||
});
|
||||
|
||||
export default welcomeRouteConfigInjectable;
|
||||
@@ -7,7 +7,7 @@ import type { ReadOptions } from "fs-extra";
|
||||
import fse from "fs-extra";
|
||||
|
||||
/**
|
||||
* NOTE: Add corrisponding a corrisponding override of this injecable in `src/test-utils/override-fs-with-fakes.ts`
|
||||
* NOTE: Add corresponding override of this injectable in `src/test-utils/override-fs-with-fakes.ts`
|
||||
*/
|
||||
const fsInjectable = getInjectable({
|
||||
id: "fs",
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*/
|
||||
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import createClusterInjectable from "../../../main/create-cluster/create-cluster.injectable";
|
||||
import clusterFrameContextForNamespacedResourcesInjectable from "../../../renderer/cluster-frame-context/for-namespaced-resources.injectable";
|
||||
import hostedClusterInjectable from "../../../renderer/cluster-frame-context/hosted-cluster.injectable";
|
||||
import { getDiForUnitTesting } from "../../../renderer/getDiForUnitTesting";
|
||||
@@ -18,6 +17,10 @@ import { KubeApi } from "../kube-api";
|
||||
import { KubeObject } from "../kube-object";
|
||||
import { KubeObjectStore } from "../kube-object.store";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
import { createClusterInjectionToken } from "../../cluster/create-cluster-injection-token";
|
||||
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { KubeApi as ExternalKubeApi } from "../../../extensions/common-api/k8s-api";
|
||||
|
||||
class TestApi extends KubeApi<KubeObject> {
|
||||
protected async checkPreferredVersion() {
|
||||
@@ -40,7 +43,7 @@ describe("ApiManager", () => {
|
||||
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
|
||||
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||
|
||||
const createCluster = di.inject(createClusterInjectable);
|
||||
const createCluster = di.inject(createClusterInjectionToken);
|
||||
|
||||
di.override(hostedClusterInjectable, () => createCluster({
|
||||
contextName: "some-context-name",
|
||||
@@ -54,7 +57,7 @@ describe("ApiManager", () => {
|
||||
});
|
||||
|
||||
describe("registerApi", () => {
|
||||
it("re-register store if apiBase changed", async () => {
|
||||
it("re-register store if apiBase changed", () => {
|
||||
const apiBase = "apis/v1/foo";
|
||||
const fallbackApiBase = "/apis/extensions/v1beta1/foo";
|
||||
const kubeApi = new TestApi({
|
||||
@@ -72,21 +75,48 @@ describe("ApiManager", () => {
|
||||
logger: di.inject(loggerInjectable),
|
||||
}, kubeApi);
|
||||
|
||||
apiManager.registerApi(apiBase, kubeApi);
|
||||
apiManager.registerApi(kubeApi);
|
||||
|
||||
// Define to use test api for ingress store
|
||||
Object.defineProperty(kubeStore, "api", { value: kubeApi });
|
||||
apiManager.registerStore(kubeStore, [kubeApi]);
|
||||
apiManager.registerStore(kubeStore);
|
||||
|
||||
// Test that store is returned with original apiBase
|
||||
expect(apiManager.getStore(kubeApi)).toBe(kubeStore);
|
||||
|
||||
// Change apiBase similar as checkPreferredVersion does
|
||||
Object.defineProperty(kubeApi, "apiBase", { value: fallbackApiBase });
|
||||
apiManager.registerApi(fallbackApiBase, kubeApi);
|
||||
apiManager.registerApi(kubeApi);
|
||||
|
||||
// Test that store is returned with new apiBase
|
||||
expect(apiManager.getStore(kubeApi)).toBe(kubeStore);
|
||||
});
|
||||
});
|
||||
|
||||
describe("technical tests for autorun", () => {
|
||||
it("given two extensions register apis with the same apibase, settle into using the second", () => {
|
||||
const apiBase = "/apis/aquasecurity.github.io/v1alpha1/vulnerabilityreports";
|
||||
const firstApi = Object.assign(new ExternalKubeApi({
|
||||
objectConstructor: KubeObject,
|
||||
apiBase,
|
||||
kind: "VulnerabilityReport",
|
||||
}), {
|
||||
myField: 1,
|
||||
});
|
||||
const secondApi = Object.assign(new ExternalKubeApi({
|
||||
objectConstructor: KubeObject,
|
||||
apiBase,
|
||||
kind: "VulnerabilityReport",
|
||||
}), {
|
||||
myField: 2,
|
||||
});
|
||||
|
||||
void firstApi;
|
||||
void secondApi;
|
||||
|
||||
expect(apiManager.getApi(apiBase)).toMatchObject({
|
||||
myField: 2,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -15,7 +15,6 @@ import setupAutoRegistrationInjectable from "../../../renderer/before-frame-star
|
||||
import { createMockResponseFromString } from "../../../test-utils/mock-responses";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../../renderer/stores-apis-can-be-created.injectable";
|
||||
import directoryForUserDataInjectable from "../../app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import createClusterInjectable from "../../../main/create-cluster/create-cluster.injectable";
|
||||
import hostedClusterInjectable from "../../../renderer/cluster-frame-context/hosted-cluster.injectable";
|
||||
import directoryForKubeConfigsInjectable from "../../app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
|
||||
import apiManagerInjectable from "../api-manager/manager.injectable";
|
||||
@@ -23,6 +22,7 @@ import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import ingressApiInjectable from "../endpoints/ingress.api.injectable";
|
||||
import loggerInjectable from "../../logger.injectable";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
import { createClusterInjectionToken } from "../../cluster/create-cluster-injection-token";
|
||||
|
||||
describe("KubeApi", () => {
|
||||
let fetchMock: AsyncFnMock<Fetch>;
|
||||
@@ -39,7 +39,7 @@ describe("KubeApi", () => {
|
||||
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
|
||||
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||
|
||||
const createCluster = di.inject(createClusterInjectable);
|
||||
const createCluster = di.inject(createClusterInjectionToken);
|
||||
|
||||
di.override(hostedClusterInjectable, () => createCluster({
|
||||
contextName: "some-context-name",
|
||||
|
||||
@@ -24,7 +24,6 @@ import setupAutoRegistrationInjectable from "../../../renderer/before-frame-star
|
||||
import { createMockResponseFromStream, createMockResponseFromString } from "../../../test-utils/mock-responses";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../../renderer/stores-apis-can-be-created.injectable";
|
||||
import directoryForUserDataInjectable from "../../app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import createClusterInjectable from "../../../main/create-cluster/create-cluster.injectable";
|
||||
import hostedClusterInjectable from "../../../renderer/cluster-frame-context/hosted-cluster.injectable";
|
||||
import directoryForKubeConfigsInjectable from "../../app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
|
||||
import apiKubeInjectable from "../../../renderer/k8s/api-kube.injectable";
|
||||
@@ -36,6 +35,7 @@ import namespaceApiInjectable from "../endpoints/namespace.api.injectable";
|
||||
// NOTE: this is fine because we are testing something that only exported
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { PodsApi } from "../../../extensions/common-api/k8s-api";
|
||||
import { createClusterInjectionToken } from "../../cluster/create-cluster-injection-token";
|
||||
|
||||
describe("createKubeApiForRemoteCluster", () => {
|
||||
let createKubeApiForRemoteCluster: CreateKubeApiForRemoteCluster;
|
||||
@@ -48,7 +48,7 @@ describe("createKubeApiForRemoteCluster", () => {
|
||||
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
|
||||
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||
|
||||
const createCluster = di.inject(createClusterInjectable);
|
||||
const createCluster = di.inject(createClusterInjectionToken);
|
||||
|
||||
di.override(hostedClusterInjectable, () => createCluster({
|
||||
contextName: "some-context-name",
|
||||
@@ -154,7 +154,7 @@ describe("KubeApi", () => {
|
||||
fetchMock = asyncFn();
|
||||
di.override(fetchInjectable, () => fetchMock);
|
||||
|
||||
const createCluster = di.inject(createClusterInjectable);
|
||||
const createCluster = di.inject(createClusterInjectionToken);
|
||||
const createKubeJsonApi = di.inject(createKubeJsonApiInjectable);
|
||||
|
||||
di.override(hostedClusterInjectable, () => createCluster({
|
||||
|
||||
@@ -41,19 +41,22 @@ export class ApiManager {
|
||||
const apis = chain(this.dependencies.apis.get().values())
|
||||
.concat(this.externalApis.values());
|
||||
const removedApis = new Set(this.apis.values());
|
||||
const newState = new Map(this.apis);
|
||||
|
||||
for (const api of apis) {
|
||||
removedApis.delete(api);
|
||||
this.apis.set(api.apiBase, api);
|
||||
newState.set(api.apiBase, api);
|
||||
}
|
||||
|
||||
for (const api of removedApis) {
|
||||
for (const [apiBase, storedApi] of this.apis) {
|
||||
for (const [apiBase, storedApi] of newState) {
|
||||
if (storedApi === api) {
|
||||
this.apis.delete(apiBase);
|
||||
newState.delete(apiBase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.apis.replace(newState);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ export class ResourceStack {
|
||||
|
||||
this.dependencies.logger.warn(`[RESOURCE-STACK]: failed to apply resources: ${result.error}`);
|
||||
|
||||
return "";
|
||||
throw new Error(result.error);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,4 @@
|
||||
*/
|
||||
|
||||
// @experimental
|
||||
export { applicationInformationToken } from "./vars/application-information-token";
|
||||
export type { ApplicationInformation } from "./vars/application-information-token";
|
||||
export { bundledExtensionInjectionToken } from "../extensions/extension-discovery/bundled-extension-token";
|
||||
@@ -3,13 +3,20 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { createLogger, format } from "winston";
|
||||
import type { Logger } from "./logger";
|
||||
import winstonLoggerInjectable from "./winston-logger.injectable";
|
||||
import { loggerTransportInjectionToken } from "./logger/transports";
|
||||
|
||||
const loggerInjectable = getInjectable({
|
||||
id: "logger",
|
||||
instantiate: (di): Logger => {
|
||||
const baseLogger = di.inject(winstonLoggerInjectable);
|
||||
const baseLogger = createLogger({
|
||||
format: format.combine(
|
||||
format.splat(),
|
||||
format.simple(),
|
||||
),
|
||||
transports: di.injectMany(loggerTransportInjectionToken),
|
||||
});
|
||||
|
||||
return {
|
||||
debug: (message, ...data) => baseLogger.debug(message, ...data),
|
||||
|
||||
@@ -19,7 +19,10 @@ import asyncFn from "@async-fn/jest";
|
||||
import { getPromiseStatus } from "../../test-utils/get-promise-status";
|
||||
import { runInAction } from "mobx";
|
||||
import type { RequestChannelHandler } from "../../../main/utils/channel/channel-listeners/listener-tokens";
|
||||
import { getRequestChannelListenerInjectable } from "../../../main/utils/channel/channel-listeners/listener-tokens";
|
||||
import {
|
||||
getRequestChannelListenerInjectable,
|
||||
requestChannelListenerInjectionToken,
|
||||
} from "../../../main/utils/channel/channel-listeners/listener-tokens";
|
||||
|
||||
type TestMessageChannel = MessageChannel<string>;
|
||||
type TestRequestChannel = RequestChannel<string, string>;
|
||||
@@ -199,21 +202,32 @@ describe("channel", () => {
|
||||
it("when registering multiple handlers for the same channel, throws", async () => {
|
||||
const applicationBuilder = getApplicationBuilder();
|
||||
|
||||
const testChannelListenerInMainInjectable = getRequestChannelListenerInjectable({
|
||||
channel: testRequestChannel,
|
||||
handler: () => () => "some-value",
|
||||
});
|
||||
const testChannelListenerInMain2Injectable = getRequestChannelListenerInjectable({
|
||||
channel: testRequestChannel,
|
||||
handler: () => () => "some-other-value",
|
||||
const someChannelListenerInjectable = getInjectable({
|
||||
id: "some-channel-listener",
|
||||
|
||||
instantiate: () => ({
|
||||
channel: testRequestChannel,
|
||||
handler: () => () => "irrelevant",
|
||||
}),
|
||||
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
});
|
||||
|
||||
testChannelListenerInMain2Injectable.id += "2";
|
||||
const someOtherChannelListenerInjectable = getInjectable({
|
||||
id: "some-other-channel-listener",
|
||||
|
||||
instantiate: () => ({
|
||||
channel: testRequestChannel,
|
||||
handler: () => () => "irrelevant",
|
||||
}),
|
||||
|
||||
injectionToken: requestChannelListenerInjectionToken,
|
||||
});
|
||||
|
||||
applicationBuilder.beforeApplicationStart((mainDi) => {
|
||||
runInAction(() => {
|
||||
mainDi.register(testChannelListenerInMainInjectable);
|
||||
mainDi.register(testChannelListenerInMain2Injectable);
|
||||
mainDi.register(someChannelListenerInjectable);
|
||||
mainDi.register(someOtherChannelListenerInjectable);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ const withOrphanPromiseInjectable = getInjectable({
|
||||
toBeDecorated,
|
||||
withErrorLoggingFor(() => "Orphan promise rejection encountered"),
|
||||
withErrorSuppression,
|
||||
);
|
||||
) as ((...args: any[]) => any);
|
||||
|
||||
decorated(...args);
|
||||
};
|
||||
|
||||
@@ -18,6 +18,6 @@ export const apiKubePrefix = "/api-kube"; // k8s cluster apis
|
||||
|
||||
// Links
|
||||
export const issuesTrackerUrl = "https://github.com/lensapp/lens/issues" as string;
|
||||
export const slackUrl = "https://k8slens.dev/slack.html" as string;
|
||||
export const supportUrl = "https://docs.k8slens.dev/support/" as string;
|
||||
export const docsUrl = "https://docs.k8slens.dev" as string;
|
||||
export const forumsUrl = "https://forums.k8slens.dev" as string;
|
||||
@@ -2,8 +2,8 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { applicationInformationToken } from "@k8slens/application";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { applicationInformationToken } from "./application-information-token";
|
||||
|
||||
const applicationCopyrightInjectable = getInjectable({
|
||||
id: "application-copyright",
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { applicationInformationToken } from "@k8slens/application";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { applicationInformationToken } from "./application-information-token";
|
||||
|
||||
const applicationDescriptionInjectable = getInjectable({
|
||||
id: "application-description",
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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 { applicationInformationToken } from "@k8slens/application";
|
||||
|
||||
export const applicationInformationFakeInjectable = getInjectable({
|
||||
id: "application-information-fake",
|
||||
|
||||
instantiate: () => ({
|
||||
name: "some-product-name",
|
||||
productName: "some-product-name",
|
||||
version: "6.0.0",
|
||||
updatingIsEnabled: false,
|
||||
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",
|
||||
}),
|
||||
|
||||
injectionToken: applicationInformationToken,
|
||||
});
|
||||
@@ -1,20 +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 packageJson from "../../../package.json";
|
||||
import { applicationInformationToken } from "../../common/vars/application-information-token";
|
||||
|
||||
const applicationInformationInjectable = getInjectable({
|
||||
id: "application-information",
|
||||
injectionToken: applicationInformationToken,
|
||||
instantiate: () => {
|
||||
const { version, config, productName, build, copyright, description, name } = packageJson;
|
||||
|
||||
return { version, config, productName, build, copyright, description, name };
|
||||
},
|
||||
causesSideEffects: true,
|
||||
});
|
||||
|
||||
export default applicationInformationInjectable;
|
||||
@@ -1,15 +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 packageJson from "../../../package.json";
|
||||
|
||||
export type ApplicationInformation = Pick<typeof packageJson, "version" | "config" | "productName" | "copyright" | "description" | "name"> & {
|
||||
build: Partial<typeof packageJson["build"]> & { publish?: unknown[] };
|
||||
};
|
||||
|
||||
export const applicationInformationToken = getInjectionToken<ApplicationInformation>({
|
||||
id: "application-information-token",
|
||||
});
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { getGlobalOverride } from "../test-utils/get-global-override";
|
||||
import applicationInformationInjectable from "./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",
|
||||
}));
|
||||
@@ -2,12 +2,12 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { applicationInformationToken } from "@k8slens/application";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { applicationInformationToken } from "./application-information-token";
|
||||
|
||||
const bundledKubectlVersionInjectable = getInjectable({
|
||||
id: "bundled-kubectl-version",
|
||||
instantiate: (di) => di.inject(applicationInformationToken).config.bundledKubectlVersion,
|
||||
instantiate: (di) => di.inject(applicationInformationToken).bundledKubectlVersion,
|
||||
});
|
||||
|
||||
export default bundledKubectlVersionInjectable;
|
||||
@@ -2,12 +2,12 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { applicationInformationToken } from "@k8slens/application";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { applicationInformationToken } from "./application-information-token";
|
||||
|
||||
const contentSecurityPolicyInjectable = getInjectable({
|
||||
id: "content-security-policy",
|
||||
instantiate: (di) => di.inject(applicationInformationToken).config.contentSecurityPolicy,
|
||||
instantiate: (di) => di.inject(applicationInformationToken).contentSecurityPolicy,
|
||||
});
|
||||
|
||||
export default contentSecurityPolicyInjectable;
|
||||
@@ -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 nodeEnvInjectionToken from "./node-env-injection-token";
|
||||
|
||||
const nodeEnvFakeInjectable = getInjectable({
|
||||
id: "node-env-fake",
|
||||
instantiate: () => "production",
|
||||
injectionToken: nodeEnvInjectionToken,
|
||||
});
|
||||
|
||||
export default nodeEnvFakeInjectable;
|
||||
@@ -2,8 +2,8 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { applicationInformationToken } from "@k8slens/application";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { applicationInformationToken } from "./application-information-token";
|
||||
|
||||
const productNameInjectable = getInjectable({
|
||||
id: "product-name",
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { applicationInformationToken } from "@k8slens/application";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { applicationInformationToken } from "./application-information-token";
|
||||
|
||||
const sentryDataSourceNameInjectable = getInjectable({
|
||||
id: "sentry-data-source-name",
|
||||
instantiate: (di) => di.inject(applicationInformationToken).config.sentryDsn,
|
||||
instantiate: (di) => di.inject(applicationInformationToken).sentryDsn,
|
||||
});
|
||||
|
||||
export default sentryDataSourceNameInjectable;
|
||||
@@ -3,11 +3,10 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { applicationInformationToken } from "./application-information-token";
|
||||
|
||||
const storeMigrationVersionInjectable = getInjectable({
|
||||
id: "store-migration-version",
|
||||
instantiate: (di) => di.inject(applicationInformationToken).version,
|
||||
instantiate: () => "6.4.0",
|
||||
});
|
||||
|
||||
export default storeMigrationVersionInjectable;
|
||||
@@ -1,20 +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 { createLogger, format } from "winston";
|
||||
import { loggerTransportInjectionToken } from "./logger/transports";
|
||||
|
||||
const winstonLoggerInjectable = getInjectable({
|
||||
id: "winston-logger",
|
||||
instantiate: (di) => createLogger({
|
||||
format: format.combine(
|
||||
format.splat(),
|
||||
format.simple(),
|
||||
),
|
||||
transports: di.injectMany(loggerTransportInjectionToken),
|
||||
}),
|
||||
});
|
||||
|
||||
export default winstonLoggerInjectable;
|
||||
+2
-2
@@ -9,7 +9,7 @@ import {
|
||||
createContainer,
|
||||
getInjectable,
|
||||
} from "@ogre-tools/injectable";
|
||||
import { Environments, setLegacyGlobalDiForExtensionApi } from "./legacy-global-di-for-extension-api";
|
||||
import { setLegacyGlobalDiForExtensionApi } from "./legacy-global-di-for-extension-api";
|
||||
import { asLegacyGlobalObjectForExtensionApiWithModifications } from "./as-legacy-global-object-for-extension-api-with-modifications";
|
||||
|
||||
describe("asLegacyGlobalObjectForExtensionApiWithModifications", () => {
|
||||
@@ -25,7 +25,7 @@ describe("asLegacyGlobalObjectForExtensionApiWithModifications", () => {
|
||||
|
||||
jest.spyOn(di, "inject");
|
||||
|
||||
setLegacyGlobalDiForExtensionApi(di, Environments.renderer);
|
||||
setLegacyGlobalDiForExtensionApi(di, "renderer");
|
||||
|
||||
someInjectable = getInjectable({
|
||||
id: "some-injectable",
|
||||
|
||||
+3
-9
@@ -4,17 +4,11 @@
|
||||
*/
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
|
||||
export type Environments = "main" | "renderer";
|
||||
|
||||
const legacyGlobalDis = new Map<Environments, DiContainer>();
|
||||
|
||||
export enum Environments {
|
||||
renderer,
|
||||
main,
|
||||
}
|
||||
|
||||
export const setLegacyGlobalDiForExtensionApi = (
|
||||
di: DiContainer,
|
||||
environment: Environments,
|
||||
) => {
|
||||
export const setLegacyGlobalDiForExtensionApi = (di: DiContainer, environment: Environments) => {
|
||||
legacyGlobalDis.set(environment, di);
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import isWindowsInjectable from "../../common/vars/is-windows.injectable";
|
||||
import { asLegacyGlobalFunctionForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api";
|
||||
import { getLegacyGlobalDiForExtensionApi } from "../as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
import getEnabledExtensionsInjectable from "./get-enabled-extensions/get-enabled-extensions.injectable";
|
||||
import { slackUrl, issuesTrackerUrl } from "../../common/vars";
|
||||
import { issuesTrackerUrl } from "../../common/vars";
|
||||
import { buildVersionInjectionToken } from "../../common/vars/build-semantic-version.injectable";
|
||||
import { asLegacyGlobalForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
|
||||
import userStoreInjectable from "../../common/user-store/user-store.injectable";
|
||||
@@ -53,6 +53,9 @@ export const App = {
|
||||
|
||||
return di.inject(isLinuxInjectable);
|
||||
},
|
||||
slackUrl,
|
||||
/**
|
||||
* @deprecated This value is now `""` and is left here for backwards compatability.
|
||||
*/
|
||||
slackUrl: "",
|
||||
issuesTrackerUrl,
|
||||
} as const;
|
||||
@@ -47,17 +47,29 @@ const getKubeApiDeps = (): KubeApiDependencies => {
|
||||
};
|
||||
};
|
||||
|
||||
export interface ExternalKubeApiOptions {
|
||||
/**
|
||||
* If `true` then on creation of the `KubeApi`instance a call to `apiManager.registerApi` will be
|
||||
* made. This is `true` by default to maintain backwards compatability.
|
||||
*
|
||||
* Setting this to `false` might make `KubeObject`'s details drawer stop working.
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
autoRegister?: boolean;
|
||||
}
|
||||
|
||||
// NOTE: this is done to preserve `instanceOf` behaviour
|
||||
function KubeApiCstr<
|
||||
Object extends KubeObject = KubeObject,
|
||||
Data extends KubeJsonApiDataFor<Object> = KubeJsonApiDataFor<Object>,
|
||||
>(opts: KubeApiOptions<Object, Data>) {
|
||||
>({ autoRegister = true, ...opts }: KubeApiOptions<Object, Data> & ExternalKubeApiOptions) {
|
||||
const api = new InternalKubeApi(getKubeApiDeps(), opts);
|
||||
|
||||
const di = getLegacyGlobalDiForExtensionApi();
|
||||
const storesAndApisCanBeCreated = di.inject(storesAndApisCanBeCreatedInjectionToken);
|
||||
|
||||
if (storesAndApisCanBeCreated) {
|
||||
if (storesAndApisCanBeCreated && autoRegister) {
|
||||
apiManager.registerApi(api);
|
||||
}
|
||||
|
||||
@@ -72,7 +84,7 @@ export type KubeApi<
|
||||
export const KubeApi = KubeApiCstr as unknown as new<
|
||||
Object extends KubeObject = KubeObject,
|
||||
Data extends KubeJsonApiDataFor<Object> = KubeJsonApiDataFor<Object>,
|
||||
>(opts: KubeApiOptions<Object, Data>) => InternalKubeApi<Object, Data>;
|
||||
>(opts: KubeApiOptions<Object, Data> & ExternalKubeApiOptions) => InternalKubeApi<Object, Data>;
|
||||
|
||||
/**
|
||||
* @deprecated Switch to using `Common.createResourceStack` instead
|
||||
|
||||
@@ -8,8 +8,8 @@ import extensionLoaderInjectable from "../extension-loader/extension-loader.inje
|
||||
import isCompatibleExtensionInjectable from "./is-compatible-extension/is-compatible-extension.injectable";
|
||||
import extensionsStoreInjectable from "../extensions-store/extensions-store.injectable";
|
||||
import extensionInstallationStateStoreInjectable from "../extension-installation-state-store/extension-installation-state-store.injectable";
|
||||
import installExtensionInjectable from "../extension-installer/install-extension/install-extension.injectable";
|
||||
import extensionPackageRootDirectoryInjectable from "../extension-installer/extension-package-root-directory/extension-package-root-directory.injectable";
|
||||
import installExtensionInjectable from "../install-extension/install-extension.injectable";
|
||||
import extensionPackageRootDirectoryInjectable from "../install-extension/extension-package-root-directory.injectable";
|
||||
import readJsonFileInjectable from "../../common/fs/read-json-file.injectable";
|
||||
import loggerInjectable from "../../common/logger.injectable";
|
||||
import pathExistsInjectable from "../../common/fs/path-exists.injectable";
|
||||
|
||||
@@ -7,7 +7,7 @@ import type { FSWatcher } from "chokidar";
|
||||
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
|
||||
import extensionDiscoveryInjectable from "../extension-discovery/extension-discovery.injectable";
|
||||
import type { ExtensionDiscovery } from "../extension-discovery/extension-discovery";
|
||||
import installExtensionInjectable from "../extension-installer/install-extension/install-extension.injectable";
|
||||
import installExtensionInjectable from "../install-extension/install-extension.injectable";
|
||||
import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import { delay } from "../../renderer/utils";
|
||||
import { observable, runInAction, when } from "mobx";
|
||||
|
||||
@@ -1,21 +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 pathToNpmCliInjectable from "../../common/app-paths/path-to-npm-cli.injectable";
|
||||
import loggerInjectable from "../../common/logger.injectable";
|
||||
import { ExtensionInstaller } from "./extension-installer";
|
||||
import extensionPackageRootDirectoryInjectable from "./extension-package-root-directory/extension-package-root-directory.injectable";
|
||||
|
||||
const extensionInstallerInjectable = getInjectable({
|
||||
id: "extension-installer",
|
||||
|
||||
instantiate: (di) => new ExtensionInstaller({
|
||||
extensionPackageRootDirectory: di.inject(extensionPackageRootDirectoryInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
pathToNpmCli: di.inject(pathToNpmCliInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
export default extensionInstallerInjectable;
|
||||
@@ -1,78 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import AwaitLock from "await-lock";
|
||||
import child_process from "child_process";
|
||||
import type { Logger } from "../../common/logger";
|
||||
|
||||
const logModule = "[EXTENSION-INSTALLER]";
|
||||
|
||||
interface Dependencies {
|
||||
readonly extensionPackageRootDirectory: string;
|
||||
readonly logger: Logger;
|
||||
readonly pathToNpmCli: string;
|
||||
}
|
||||
|
||||
const baseNpmInstallArgs = [
|
||||
"install",
|
||||
"--audit=false",
|
||||
"--fund=false",
|
||||
// NOTE: we do not omit the `optional` dependencies because that is how we specify the non-bundled extensions
|
||||
"--omit=dev",
|
||||
"--omit=peer",
|
||||
"--prefer-offline",
|
||||
];
|
||||
|
||||
/**
|
||||
* Installs dependencies for extensions
|
||||
*/
|
||||
export class ExtensionInstaller {
|
||||
private readonly installLock = new AwaitLock();
|
||||
|
||||
constructor(private readonly dependencies: Dependencies) {}
|
||||
|
||||
/**
|
||||
* Install single package using npm
|
||||
*/
|
||||
installPackage = async (name: string): Promise<void> => {
|
||||
// Mutual exclusion to install packages in sequence
|
||||
await this.installLock.acquireAsync();
|
||||
|
||||
try {
|
||||
this.dependencies.logger.info(`${logModule} installing package from ${name} to ${this.dependencies.extensionPackageRootDirectory}`);
|
||||
await this.npm(...baseNpmInstallArgs, name);
|
||||
this.dependencies.logger.info(`${logModule} package ${name} installed to ${this.dependencies.extensionPackageRootDirectory}`);
|
||||
} finally {
|
||||
this.installLock.release();
|
||||
}
|
||||
};
|
||||
|
||||
private npm(...args: string[]): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = child_process.fork(this.dependencies.pathToNpmCli, args, {
|
||||
cwd: this.dependencies.extensionPackageRootDirectory,
|
||||
silent: true,
|
||||
env: {},
|
||||
});
|
||||
let stderr = "";
|
||||
|
||||
child.stderr?.on("data", data => {
|
||||
stderr += String(data);
|
||||
});
|
||||
|
||||
child.on("close", (code) => {
|
||||
if (code !== 0) {
|
||||
reject(new Error(stderr));
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
child.on("error", error => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
-13
@@ -1,13 +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 extensionInstallerInjectable from "../extension-installer.injectable";
|
||||
|
||||
const installExtensionInjectable = getInjectable({
|
||||
id: "install-extension",
|
||||
instantiate: (di) => di.inject(extensionInstallerInjectable).installPackage,
|
||||
});
|
||||
|
||||
export default installExtensionInjectable;
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
|
||||
const extensionPackageRootDirectoryInjectable = getInjectable({
|
||||
id: "extension-package-root-directory",
|
||||
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* 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 { fork } from "child_process";
|
||||
import AwaitLock from "await-lock";
|
||||
import pathToNpmCliInjectable from "../../common/app-paths/path-to-npm-cli.injectable";
|
||||
import extensionPackageRootDirectoryInjectable from "./extension-package-root-directory.injectable";
|
||||
import prefixedLoggerInjectable from "../../common/logger/prefixed-logger.injectable";
|
||||
import readJsonFileInjectable from "../../common/fs/read-json-file.injectable";
|
||||
import joinPathsInjectable from "../../common/path/join-paths.injectable";
|
||||
import type { PackageJson } from "../common-api";
|
||||
import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable";
|
||||
import { once } from "lodash";
|
||||
import { isErrnoException } from "../../common/utils";
|
||||
|
||||
const baseNpmInstallArgs = [
|
||||
"install",
|
||||
"--save-optional",
|
||||
"--audit=false",
|
||||
"--fund=false",
|
||||
// NOTE: we do not omit the `optional` dependencies because that is how we specify the non-bundled extensions
|
||||
"--omit=dev",
|
||||
"--omit=peer",
|
||||
"--prefer-offline",
|
||||
];
|
||||
|
||||
export type InstallExtension = (name: string) => Promise<void>;
|
||||
|
||||
const installExtensionInjectable = getInjectable({
|
||||
id: "install-extension",
|
||||
instantiate: (di): InstallExtension => {
|
||||
const pathToNpmCli = di.inject(pathToNpmCliInjectable);
|
||||
const extensionPackageRootDirectory = di.inject(extensionPackageRootDirectoryInjectable);
|
||||
const readJsonFile = di.inject(readJsonFileInjectable);
|
||||
const writeJsonFile = di.inject(writeJsonFileInjectable);
|
||||
const joinPaths = di.inject(joinPathsInjectable);
|
||||
const logger = di.inject(prefixedLoggerInjectable, "EXTENSION-INSTALLER");
|
||||
|
||||
const forkNpm = (...args: string[]) => new Promise<void>((resolve, reject) => {
|
||||
const child = fork(pathToNpmCli, args, {
|
||||
cwd: extensionPackageRootDirectory,
|
||||
silent: true,
|
||||
env: {},
|
||||
});
|
||||
let stderr = "";
|
||||
|
||||
child.stderr?.on("data", data => {
|
||||
stderr += String(data);
|
||||
});
|
||||
|
||||
child.on("close", (code) => {
|
||||
if (code !== 0) {
|
||||
reject(new Error(stderr));
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
child.on("error", error => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
|
||||
const packageJsonPath = joinPaths(extensionPackageRootDirectory, "package.json");
|
||||
|
||||
/**
|
||||
* NOTES:
|
||||
* - We have to keep the `package.json` because `npm install` removes files from `node_modules`
|
||||
* if they are no longer in the `package.json`
|
||||
* - In v6.2.X we saved bundled extensions as `"dependencies"` and external extensions as
|
||||
* `"optionalDependencies"` at startup. This was done because `"optionalDependencies"` can
|
||||
* fail to install and that is OK.
|
||||
* - We continue to maintain this behavior here by only installing new dependencies as
|
||||
* `"optionalDependencies"`
|
||||
*/
|
||||
const fixupPackageJson = once(async () => {
|
||||
try {
|
||||
const packageJson = await readJsonFile(packageJsonPath) as PackageJson;
|
||||
|
||||
delete packageJson.dependencies;
|
||||
|
||||
await writeJsonFile(packageJsonPath, packageJson);
|
||||
} catch (error) {
|
||||
if (isErrnoException(error) && error.code === "ENOENT") {
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
const installLock = new AwaitLock();
|
||||
|
||||
return async (name) => {
|
||||
await installLock.acquireAsync();
|
||||
await fixupPackageJson();
|
||||
|
||||
try {
|
||||
logger.info(`installing package for extension "${name}"`);
|
||||
await forkNpm(...baseNpmInstallArgs, name);
|
||||
logger.info(`installed package for extension "${name}"`);
|
||||
} finally {
|
||||
installLock.release();
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default installExtensionInjectable;
|
||||
@@ -3,16 +3,11 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import {
|
||||
Environments,
|
||||
getEnvironmentSpecificLegacyGlobalDiForExtensionApi,
|
||||
} from "../as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
|
||||
import { getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "../as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
|
||||
import navigateInjectable from "../../main/start-main-application/lens-window/navigate.injectable";
|
||||
|
||||
export function navigate(url: string) {
|
||||
const di = getEnvironmentSpecificLegacyGlobalDiForExtensionApi(Environments.main);
|
||||
|
||||
const di = getEnvironmentSpecificLegacyGlobalDiForExtensionApi("main");
|
||||
const navigate = di.inject(navigateInjectable);
|
||||
|
||||
return navigate(url);
|
||||
|
||||
+2
-2
@@ -107,11 +107,11 @@ exports[`extension special characters in page registrations renders 1`] = `
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
@@ -107,11 +107,11 @@ exports[`navigate to extension page renders 1`] = `
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
+2
-2
@@ -107,11 +107,11 @@ exports[`add-cluster - navigation using application menu renders 1`] = `
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
+12
-12
@@ -108,11 +108,11 @@ exports[`installing update when started renders 1`] = `
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -393,11 +393,11 @@ exports[`installing update when started when user checks for updates renders 1`]
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -678,11 +678,11 @@ exports[`installing update when started when user checks for updates when new up
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -988,11 +988,11 @@ exports[`installing update when started when user checks for updates when new up
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -1298,11 +1298,11 @@ exports[`installing update when started when user checks for updates when new up
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -1583,11 +1583,11 @@ exports[`installing update when started when user checks for updates when no new
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
+4
-4
@@ -133,11 +133,11 @@ exports[`encourage user to update when sufficient time passed since update was d
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -418,11 +418,11 @@ exports[`encourage user to update when sufficient time passed since update was d
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
+12
-12
@@ -108,11 +108,11 @@ exports[`installing update using tray when started renders 1`] = `
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -393,11 +393,11 @@ exports[`installing update using tray when started when user checks for updates
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -678,11 +678,11 @@ exports[`installing update using tray when started when user checks for updates
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -988,11 +988,11 @@ exports[`installing update using tray when started when user checks for updates
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -1298,11 +1298,11 @@ exports[`installing update using tray when started when user checks for updates
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -1583,11 +1583,11 @@ exports[`installing update using tray when started when user checks for updates
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
+6
-6
@@ -133,11 +133,11 @@ exports[`force user to update when too long since update was downloaded when app
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -443,11 +443,11 @@ exports[`force user to update when too long since update was downloaded when app
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -800,11 +800,11 @@ exports[`force user to update when too long since update was downloaded when app
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
+2
-2
@@ -108,11 +108,11 @@ exports[`periodical checking of updates given updater is enabled and configurati
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
+2
-2
@@ -108,11 +108,11 @@ exports[`selection of update stability when started renders 1`] = `
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
+2
-2
@@ -2,12 +2,12 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { applicationInformationToken } from "@k8slens/application";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { applicationInformationToken } from "../../../../../common/vars/application-information-token";
|
||||
|
||||
const publishIsConfiguredInjectable = getInjectable({
|
||||
id: "publish-is-configured",
|
||||
instantiate: (di) => Boolean(di.inject(applicationInformationToken).build.publish?.length),
|
||||
instantiate: (di) => Boolean(di.inject(applicationInformationToken).updatingIsEnabled),
|
||||
});
|
||||
|
||||
export default publishIsConfiguredInjectable;
|
||||
+2
-2
@@ -108,11 +108,11 @@ exports[`opening catalog entity details panel renders 1`] = `
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
@@ -25,6 +25,17 @@ describe("opening catalog entity details panel", () => {
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
// TODO: remove once ClusterStore can be used without overriding it
|
||||
windowDi.override(getClusterByIdInjectable, () => (clusterId) => {
|
||||
if (clusterId === cluster.id) {
|
||||
return cluster;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
});
|
||||
});
|
||||
|
||||
builder.afterWindowStart((windowDi) => {
|
||||
const createCluster = windowDi.inject(createClusterInjectable);
|
||||
|
||||
@@ -78,15 +89,6 @@ describe("opening catalog entity details panel", () => {
|
||||
clusterServerUrl: "https://localhost:9999",
|
||||
});
|
||||
|
||||
// TODO: remove once ClusterStore can be used without overriding it
|
||||
windowDi.override(getClusterByIdInjectable, () => (clusterId) => {
|
||||
if (clusterId === cluster.id) {
|
||||
return cluster;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
});
|
||||
|
||||
// TODO: replace with proper entity source once syncing entities between main and windows is injectable
|
||||
const catalogEntityRegistry = windowDi.inject(catalogEntityRegistryInjectable);
|
||||
|
||||
|
||||
+16
-16
@@ -199,11 +199,11 @@ exports[`Command Pallet: keyboard shortcut tests when on linux renders 1`] = `
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -575,11 +575,11 @@ exports[`Command Pallet: keyboard shortcut tests when on linux when pressing ESC
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -951,11 +951,11 @@ exports[`Command Pallet: keyboard shortcut tests when on linux when pressing SHI
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -1339,11 +1339,11 @@ exports[`Command Pallet: keyboard shortcut tests when on linux when pressing SHI
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -1624,11 +1624,11 @@ exports[`Command Pallet: keyboard shortcut tests when on macOS renders 1`] = `
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -1909,11 +1909,11 @@ exports[`Command Pallet: keyboard shortcut tests when on macOS when pressing ESC
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -2194,11 +2194,11 @@ exports[`Command Pallet: keyboard shortcut tests when on macOS when pressing SHI
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -2491,11 +2491,11 @@ exports[`Command Pallet: keyboard shortcut tests when on macOS when pressing SHI
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
+36
-3
@@ -108,11 +108,11 @@ exports[`Showing correct entity settings renders 1`] = `
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -830,7 +830,40 @@ exports[`Showing correct entity settings when navigating to non-local cluster en
|
||||
>
|
||||
Proxy
|
||||
</h2>
|
||||
<section />
|
||||
<section>
|
||||
<section>
|
||||
<div
|
||||
class="SubTitle"
|
||||
id="http-proxy"
|
||||
>
|
||||
HTTP Proxy
|
||||
|
||||
</div>
|
||||
<div
|
||||
class="Input theme round black"
|
||||
>
|
||||
<label
|
||||
class="input-area flex gaps align-center"
|
||||
id=""
|
||||
>
|
||||
<input
|
||||
class="input box grow"
|
||||
placeholder="http://<address>:<port>"
|
||||
spellcheck="false"
|
||||
value=""
|
||||
/>
|
||||
</label>
|
||||
<div
|
||||
class="input-info flex gaps"
|
||||
/>
|
||||
</div>
|
||||
<small
|
||||
class="hint"
|
||||
>
|
||||
HTTP Proxy server. Used for communicating with Kubernetes API.
|
||||
</small>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
<div
|
||||
|
||||
+11
-8
@@ -25,6 +25,17 @@ describe("Showing correct entity settings", () => {
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
builder.beforeWindowStart((windowDi) => {
|
||||
// TODO: remove once ClusterStore can be used without overriding it
|
||||
windowDi.override(getClusterByIdInjectable, () => (clusterId) => {
|
||||
if (clusterId === cluster.id) {
|
||||
return cluster;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
});
|
||||
});
|
||||
|
||||
builder.afterWindowStart((windowDi) => {
|
||||
const createCluster = windowDi.inject(createClusterInjectable);
|
||||
|
||||
@@ -78,14 +89,6 @@ describe("Showing correct entity settings", () => {
|
||||
clusterServerUrl: "https://localhost:9999",
|
||||
});
|
||||
|
||||
// TODO: remove once ClusterStore can be used without overriding it
|
||||
windowDi.override(getClusterByIdInjectable, () => (clusterId) => {
|
||||
if (clusterId === cluster.id) {
|
||||
return cluster;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
});
|
||||
|
||||
// TODO: replace with proper entity source once syncing entities between main and windows is injectable
|
||||
const catalogEntityRegistry = windowDi.inject(catalogEntityRegistryInjectable);
|
||||
|
||||
+2
-2
@@ -107,11 +107,11 @@ exports[`extensions - navigation using application menu renders 1`] = `
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
+2
-2
@@ -107,11 +107,11 @@ exports[`preferences - navigation using application menu renders 1`] = `
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
+2
-2
@@ -108,11 +108,11 @@ exports[`show-about-using-tray renders 1`] = `
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
+2
-2
@@ -108,11 +108,11 @@ exports[`status-bar-items-originating-from-extensions when application starts wh
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
+8
-8
@@ -108,11 +108,11 @@ exports[`extendability-using-extension-api given an extension with a weakly type
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -402,11 +402,11 @@ exports[`extendability-using-extension-api given an extension with top-bar items
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -687,11 +687,11 @@ exports[`extendability-using-extension-api given an extension with top-bar items
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -972,11 +972,11 @@ exports[`extendability-using-extension-api renders 1`] = `
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
+4
-4
@@ -107,11 +107,11 @@ exports[`welcome - navigation using application menu renders 1`] = `
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
@@ -1142,11 +1142,11 @@ exports[`welcome - navigation using application menu when navigated somewhere el
|
||||
If you have any questions or feedback, please join our
|
||||
<a
|
||||
class="link"
|
||||
href="https://k8slens.dev/slack.html"
|
||||
href="https://forums.k8slens.dev"
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
@@ -22,7 +22,10 @@ const pickHighestAccuracy = (prev: ClusterDetectionResult, curr: ClusterDetectio
|
||||
|
||||
const detectMetadataWithFor = (cluster: Cluster) => async (clusterMetadataDetector: ClusterMetadataDetector) => {
|
||||
try {
|
||||
return await clusterMetadataDetector.detect(cluster);
|
||||
return {
|
||||
key: clusterMetadataDetector.key,
|
||||
result: await clusterMetadataDetector.detect(cluster),
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
@@ -39,7 +42,12 @@ const detectClusterMetadataInjectable = getInjectable({
|
||||
filter(isDefined),
|
||||
(arg) => groupBy(arg, "key"),
|
||||
(arg) => object.entries(arg),
|
||||
map(([ key, results ]) => [key, reduce(results, pickHighestAccuracy)] as const),
|
||||
map(([ key, detectionResults ]) => {
|
||||
const results = detectionResults.map(({ result }) => result as ClusterDetectionResult);
|
||||
const highestAccuracyResult = reduce(results, pickHighestAccuracy)?.value;
|
||||
|
||||
return [key, highestAccuracyResult] as const;
|
||||
}),
|
||||
filter(hasDefinedTupleValue),
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { AppPaths } from "../../common/app-paths/app-path-injection-token";
|
||||
import appPathsStateInjectable from "../../common/app-paths/app-paths-state.injectable";
|
||||
import directoryForKubeConfigsInjectable from "../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
|
||||
import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import { ClusterMetadataKey } from "../../common/cluster-types";
|
||||
import type { Cluster } from "../../common/cluster/cluster";
|
||||
import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token";
|
||||
import { getDiForUnitTesting } from "../getDiForUnitTesting";
|
||||
import clusterDistributionDetectorInjectable from "./cluster-distribution-detector.injectable";
|
||||
import clusterIdDetectorFactoryInjectable from "./cluster-id-detector.injectable";
|
||||
import clusterLastSeenDetectorInjectable from "./cluster-last-seen-detector.injectable";
|
||||
import clusterNodeCountDetectorInjectable from "./cluster-nodes-count-detector.injectable";
|
||||
import type { DetectClusterMetadata } from "./detect-cluster-metadata.injectable";
|
||||
import detectClusterMetadataInjectable from "./detect-cluster-metadata.injectable";
|
||||
import requestClusterVersionInjectable from "./request-cluster-version.injectable";
|
||||
|
||||
describe("detect-cluster-metadata", () => {
|
||||
let detectClusterMetadata: DetectClusterMetadata;
|
||||
|
||||
let cluster: Cluster;
|
||||
|
||||
beforeEach(async () => {
|
||||
const di = getDiForUnitTesting({ doGeneralOverrides: true });
|
||||
|
||||
const lastSeenDetectMock = jest.fn().mockReturnValue(Promise.resolve({ value: "some-time-stamp", accuracy: 100 }));
|
||||
const nodeCountDetectMock = jest.fn().mockReturnValue(Promise.resolve({ value: 42, accuracy: 100 }));
|
||||
const clusterIdDetectMock = jest.fn().mockReturnValue(Promise.resolve({ value: "some-cluster-id", accuracy: 100 }));
|
||||
const distributionDetectMock = jest.fn().mockReturnValue(Promise.resolve({ value: "some-distribution", accuracy: 100 }));
|
||||
|
||||
di.override(clusterLastSeenDetectorInjectable, () => {
|
||||
return {
|
||||
key: ClusterMetadataKey.LAST_SEEN,
|
||||
detect: lastSeenDetectMock,
|
||||
};
|
||||
});
|
||||
|
||||
di.override(requestClusterVersionInjectable, () => () => Promise.resolve("some-cluster-version"));
|
||||
|
||||
di.override(clusterNodeCountDetectorInjectable, () => ({
|
||||
key: ClusterMetadataKey.NODES_COUNT,
|
||||
detect: nodeCountDetectMock,
|
||||
}));
|
||||
|
||||
di.override(clusterIdDetectorFactoryInjectable, () => ({
|
||||
key: ClusterMetadataKey.CLUSTER_ID,
|
||||
detect: clusterIdDetectMock,
|
||||
}));
|
||||
|
||||
di.override(clusterDistributionDetectorInjectable, () => ({
|
||||
key: ClusterMetadataKey.DISTRIBUTION,
|
||||
detect: distributionDetectMock,
|
||||
}));
|
||||
|
||||
di.override(directoryForUserDataInjectable, () => "/some-user-store-path");
|
||||
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
|
||||
di.override(appPathsStateInjectable, () => ({
|
||||
get: () => ({} as AppPaths),
|
||||
set: () => {},
|
||||
}));
|
||||
|
||||
detectClusterMetadata = di.inject(detectClusterMetadataInjectable);
|
||||
|
||||
const createCluster = di.inject(createClusterInjectionToken);
|
||||
|
||||
cluster = createCluster({
|
||||
id: "some-id",
|
||||
contextName: "some-context",
|
||||
kubeConfigPath: "minikube-config.yml",
|
||||
}, {
|
||||
clusterServerUrl: "foo",
|
||||
});
|
||||
});
|
||||
|
||||
it("given some cluster, last seen time stamp is added to the metadata", async () => {
|
||||
const metadata = await detectClusterMetadata(cluster);
|
||||
|
||||
expect(metadata.lastSeen).toEqual("some-time-stamp");
|
||||
});
|
||||
|
||||
it("given some cluster, cluster version is added to the metadata", async () => {
|
||||
const metadata = await detectClusterMetadata(cluster);
|
||||
|
||||
expect(metadata.version).toEqual("some-cluster-version");
|
||||
});
|
||||
|
||||
it("given some cluster, id is added to the metadata", async () => {
|
||||
const metadata = await detectClusterMetadata(cluster);
|
||||
|
||||
expect(metadata.id).toEqual("some-cluster-id");
|
||||
});
|
||||
|
||||
it("given some cluster, node count is added to the metadata", async () => {
|
||||
const metadata = await detectClusterMetadata(cluster);
|
||||
|
||||
expect(metadata.nodes).toEqual(42);
|
||||
});
|
||||
|
||||
it("given some cluster, distribution is added to the metadata", async () => {
|
||||
const metadata = await detectClusterMetadata(cluster);
|
||||
|
||||
expect(metadata.distribution).toEqual("some-distribution");
|
||||
});
|
||||
});
|
||||
@@ -6,12 +6,12 @@
|
||||
// Fix embedded kubeconfig paths under snap config
|
||||
|
||||
import { getInjectable } from "@ogre-tools/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";
|
||||
import type { ClusterModel } from "../../../common/cluster-types";
|
||||
import pathExistsSyncInjectable from "../../../common/fs/path-exists-sync.injectable";
|
||||
import { applicationInformationToken } from "@k8slens/application";
|
||||
|
||||
const clusterStoreSnapMigrationInjectable = getInjectable({
|
||||
id: "cluster-store-snap-migration",
|
||||
|
||||
@@ -3,20 +3,17 @@
|
||||
* 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 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";
|
||||
|
||||
interface AppConfig {
|
||||
di: DiContainer;
|
||||
mode: string;
|
||||
}
|
||||
|
||||
export function createApp(conf: AppConfig) {
|
||||
const { di, mode } = conf;
|
||||
export const createApplication: CreateApplication = (config) => {
|
||||
const { mode } = config;
|
||||
const di = getDi();
|
||||
|
||||
runInAction(() => {
|
||||
di.register(getInjectable({
|
||||
@@ -28,9 +25,8 @@ export function createApp(conf: AppConfig) {
|
||||
registerInjectables(di);
|
||||
});
|
||||
|
||||
const startMainApplication = di.inject(startMainApplicationInjectable);
|
||||
|
||||
return {
|
||||
start: () => startMainApplication(),
|
||||
start: di.inject(startMainApplicationInjectable),
|
||||
di,
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -3,15 +3,15 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { createContainer } from "@ogre-tools/injectable";
|
||||
import { runInAction } from "mobx";
|
||||
import applicationInformationInjectable from "../common/vars/application-information-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 di = createContainer("main");
|
||||
const environment = "main";
|
||||
const di = createContainer(environment);
|
||||
|
||||
runInAction(() => {
|
||||
di.register(applicationInformationInjectable);
|
||||
});
|
||||
registerMobX(di);
|
||||
setLegacyGlobalDiForExtensionApi(di, environment);
|
||||
|
||||
return di;
|
||||
};
|
||||
@@ -4,9 +4,8 @@
|
||||
*/
|
||||
|
||||
import { chunk } from "lodash/fp";
|
||||
import type { DiContainer, Injectable } 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 type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { 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";
|
||||
@@ -25,45 +24,30 @@ import electronQuitAndInstallUpdateInjectable from "./electron-app/features/elec
|
||||
import electronUpdaterIsActiveInjectable from "./electron-app/features/electron-updater-is-active.injectable";
|
||||
import setUpdateOnQuitInjectable from "./electron-app/features/set-update-on-quit.injectable";
|
||||
import waitUntilBundledExtensionsAreLoadedInjectable from "./start-main-application/lens-window/application-window/wait-until-bundled-extensions-are-loaded.injectable";
|
||||
import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx";
|
||||
import electronInjectable from "./utils/resolve-system-proxy/electron.injectable";
|
||||
import initializeClusterManagerInjectable from "./cluster/initialize-manager.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";
|
||||
import { getOverrideFsWithFakes } from "../test-utils/override-fs-with-fakes";
|
||||
import { getDi } from "./getDi";
|
||||
|
||||
export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) {
|
||||
const {
|
||||
doGeneralOverrides = false,
|
||||
} = opts;
|
||||
|
||||
const di = createContainer("main");
|
||||
|
||||
di.register(getInjectable({
|
||||
id: "node-env",
|
||||
instantiate: () => "production",
|
||||
injectionToken: nodeEnvInjectionToken,
|
||||
}));
|
||||
|
||||
setLegacyGlobalDiForExtensionApi(di, Environments.main);
|
||||
const di = getDi();
|
||||
|
||||
di.preventSideEffects();
|
||||
|
||||
const injectables = (
|
||||
global.injectablePaths.main.paths
|
||||
runInAction(() => {
|
||||
const injectables = global.injectablePaths.main.paths
|
||||
.map(path => require(path))
|
||||
.flatMap(Object.values)
|
||||
.filter(isInjectable)
|
||||
) as Injectable<any, any, any>[];
|
||||
.filter(isInjectable);
|
||||
|
||||
runInAction(() => {
|
||||
registerMobX(di);
|
||||
di.register(applicationInformationInjectable);
|
||||
|
||||
chunk(100)(injectables).forEach(chunkInjectables => {
|
||||
di.register(...chunkInjectables);
|
||||
});
|
||||
for (const block of chunk(100)(injectables)) {
|
||||
di.register(...block);
|
||||
}
|
||||
});
|
||||
|
||||
if (doGeneralOverrides) {
|
||||
|
||||
@@ -8,7 +8,8 @@ export { afterApplicationIsLoadedInjectionToken } from "./start-main-application
|
||||
export { beforeApplicationIsLoadingInjectionToken } from "./start-main-application/runnable-tokens/before-application-is-loading-injection-token";
|
||||
export { beforeElectronIsReadyInjectionToken } from "./start-main-application/runnable-tokens/before-electron-is-ready-injection-token";
|
||||
export { onLoadOfApplicationInjectionToken } from "./start-main-application/runnable-tokens/on-load-of-application-injection-token";
|
||||
export { createApp } from "./create-app";
|
||||
export { createApplication } from "./create-app";
|
||||
export type { CreateApplication, Application, ApplicationConfig } from "../common/create-app";
|
||||
export * as Mobx from "mobx";
|
||||
export * as mainExtensionApi from "../extensions/main-api";
|
||||
export * as commonExtensionApi from "../extensions/common-api";
|
||||
|
||||
@@ -4,19 +4,14 @@
|
||||
*/
|
||||
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: [
|
||||
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),
|
||||
@@ -24,6 +19,4 @@ export function registerInjectables(di: DiContainer) {
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
return di;
|
||||
}
|
||||
+1
-1
@@ -13,9 +13,9 @@ 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 { applicationInformationToken } from "../../../../common/vars/application-information-token";
|
||||
import pathExistsSyncInjectable from "../../../../common/fs/path-exists-sync.injectable";
|
||||
import lensProxyCertificateInjectable from "../../../../common/certificate/lens-proxy-certificate.injectable";
|
||||
import { applicationInformationToken } from "@k8slens/application";
|
||||
|
||||
export type ElectronWindowTitleBarStyle = "hiddenInset" | "hidden" | "default" | "customButtonsOnHover";
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ export const lensWebsiteLinkName = "Lens Website";
|
||||
export const lensDocumentationWeblinkId = "lens-documentation-link";
|
||||
export const lensDocumentationWeblinkName = "Lens Documentation";
|
||||
|
||||
export const lensSlackWeblinkId = "lens-slack-link";
|
||||
export const lensSlackWeblinkName = "Lens Community Slack";
|
||||
export const lensForumsWeblinkId = "lens-forums-link";
|
||||
export const lensForumsWeblinkName = "Lens Forums";
|
||||
|
||||
export const lensTwitterWeblinkId = "lens-twitter-link";
|
||||
export const lensTwitterWeblinkName = "Lens on Twitter";
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { docsUrl, slackUrl } from "../../../common/vars";
|
||||
import { docsUrl, forumsUrl } 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";
|
||||
@@ -20,7 +20,7 @@ const v514WeblinkStoreMigrationInjectable = getInjectable({
|
||||
weblinks.push(
|
||||
{ id: "https://k8slens.dev", name: links.lensWebsiteLinkName, url: "https://k8slens.dev" },
|
||||
{ id: docsUrl, name: links.lensDocumentationWeblinkName, url: docsUrl },
|
||||
{ id: slackUrl, name: links.lensSlackWeblinkName, url: slackUrl },
|
||||
{ id: forumsUrl, name: links.lensForumsWeblinkName, url: forumsUrl },
|
||||
{ id: "https://twitter.com/k8slens", name: links.lensTwitterWeblinkName, url: "https://twitter.com/k8slens" },
|
||||
{ id: "https://medium.com/k8slens", name: links.lensBlogWeblinkName, url: "https://medium.com/k8slens" },
|
||||
{ id: "https://kubernetes.io/docs/home/", name: links.kubernetesDocumentationWeblinkName, url: "https://kubernetes.io/docs/home/" },
|
||||
|
||||
@@ -16,40 +16,40 @@ const v545Beta1WeblinkStoreMigrationInjectable = getInjectable({
|
||||
const weblinksRaw = store.get("weblinks");
|
||||
const weblinks = (Array.isArray(weblinksRaw) ? weblinksRaw : []) as WeblinkData[];
|
||||
|
||||
const lensWebsiteLink = weblinks.find(weblink => weblink.name === links.lensWebsiteLinkName);
|
||||
const lensWebsite = weblinks.find(weblink => weblink.name === links.lensWebsiteLinkName);
|
||||
|
||||
if (lensWebsiteLink) {
|
||||
lensWebsiteLink.id = links.lensWebsiteWeblinkId;
|
||||
if (lensWebsite) {
|
||||
lensWebsite.id = links.lensWebsiteWeblinkId;
|
||||
}
|
||||
|
||||
const lensDocumentationWeblinkLink = weblinks.find(weblink => weblink.name === links.lensDocumentationWeblinkName);
|
||||
const lensDocumentationWeblink = weblinks.find(weblink => weblink.name === links.lensDocumentationWeblinkName);
|
||||
|
||||
if (lensDocumentationWeblinkLink) {
|
||||
lensDocumentationWeblinkLink.id = links.lensDocumentationWeblinkId;
|
||||
if (lensDocumentationWeblink) {
|
||||
lensDocumentationWeblink.id = links.lensDocumentationWeblinkId;
|
||||
}
|
||||
|
||||
const lensSlackWeblinkLink = weblinks.find(weblink => weblink.name === links.lensSlackWeblinkName);
|
||||
const lensForumsWeblink = weblinks.find(weblink => weblink.name === links.lensForumsWeblinkName);
|
||||
|
||||
if (lensSlackWeblinkLink) {
|
||||
lensSlackWeblinkLink.id = links.lensSlackWeblinkId;
|
||||
if (lensForumsWeblink) {
|
||||
lensForumsWeblink.id = links.lensForumsWeblinkId;
|
||||
}
|
||||
|
||||
const lensTwitterWeblinkLink = weblinks.find(weblink => weblink.name === links.lensTwitterWeblinkName);
|
||||
const lensTwitterWeblink = weblinks.find(weblink => weblink.name === links.lensTwitterWeblinkName);
|
||||
|
||||
if (lensTwitterWeblinkLink) {
|
||||
lensTwitterWeblinkLink.id = links.lensTwitterWeblinkId;
|
||||
if (lensTwitterWeblink) {
|
||||
lensTwitterWeblink.id = links.lensTwitterWeblinkId;
|
||||
}
|
||||
|
||||
const lensBlogWeblinkLink = weblinks.find(weblink => weblink.name === links.lensBlogWeblinkName);
|
||||
const lensBlogWeblink = weblinks.find(weblink => weblink.name === links.lensBlogWeblinkName);
|
||||
|
||||
if (lensBlogWeblinkLink) {
|
||||
lensBlogWeblinkLink.id = links.lensBlogWeblinkId;
|
||||
if (lensBlogWeblink) {
|
||||
lensBlogWeblink.id = links.lensBlogWeblinkId;
|
||||
}
|
||||
|
||||
const kubernetesDocumentationWeblinkLink = weblinks.find(weblink => weblink.name === links.kubernetesDocumentationWeblinkName);
|
||||
const kubernetesDocumentationWeblink = weblinks.find(weblink => weblink.name === links.kubernetesDocumentationWeblinkName);
|
||||
|
||||
if (kubernetesDocumentationWeblinkLink) {
|
||||
kubernetesDocumentationWeblinkLink.id = links.kubernetesDocumentationWeblinkId;
|
||||
if (kubernetesDocumentationWeblink) {
|
||||
kubernetesDocumentationWeblink.id = links.kubernetesDocumentationWeblinkId;
|
||||
}
|
||||
|
||||
store.set("weblinks", weblinks);
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { docsUrl, slackUrl } from "../../../common/vars";
|
||||
import { docsUrl, forumsUrl } 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 { applicationInformationToken } from "../../../common/vars/application-information-token";
|
||||
import { lensDocumentationWeblinkId, lensSlackWeblinkId } from "../links";
|
||||
import { lensDocumentationWeblinkId, lensForumsWeblinkId } from "../links";
|
||||
import { applicationInformationToken } from "@k8slens/application";
|
||||
|
||||
const currentVersionWeblinkStoreMigrationInjectable = getInjectable({
|
||||
id: "current-version-weblink-store-migration",
|
||||
@@ -20,10 +20,10 @@ const currentVersionWeblinkStoreMigrationInjectable = getInjectable({
|
||||
run(store) {
|
||||
const weblinksRaw = store.get("weblinks");
|
||||
const weblinks = (Array.isArray(weblinksRaw) ? weblinksRaw : []) as WeblinkData[];
|
||||
const slackWeblink = weblinks.find(weblink => weblink.id === lensSlackWeblinkId);
|
||||
const forumsWeblink = weblinks.find(weblink => weblink.id === lensForumsWeblinkId);
|
||||
|
||||
if (slackWeblink) {
|
||||
slackWeblink.url = slackUrl;
|
||||
if (forumsWeblink) {
|
||||
forumsWeblink.url = forumsUrl;
|
||||
}
|
||||
|
||||
const docsWeblink = weblinks.find(weblink => weblink.id === lensDocumentationWeblinkId);
|
||||
@@ -32,7 +32,9 @@ const currentVersionWeblinkStoreMigrationInjectable = getInjectable({
|
||||
docsWeblink.url = docsUrl;
|
||||
}
|
||||
|
||||
store.set("weblinks", weblinks);
|
||||
const removedSlackLink = weblinks.filter(weblink => weblink.id !== "lens-slack-link");
|
||||
|
||||
store.set("weblinks", removedSlackLink);
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
@@ -46,9 +46,7 @@ export async function bootstrap(di: DiContainer) {
|
||||
}
|
||||
|
||||
try {
|
||||
await initializeApp(() => {
|
||||
unmountComponentAtNode(rootElem);
|
||||
});
|
||||
await initializeApp(() => unmountComponentAtNode(rootElem));
|
||||
} catch (error) {
|
||||
console.error(`[BOOTSTRAP]: view initialization error: ${error}`, {
|
||||
origin: location.href,
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
}
|
||||
|
||||
.catalogAvatar {
|
||||
font-size: 1.2ch;
|
||||
font-size: 1.2ch !important;
|
||||
}
|
||||
|
||||
.views {
|
||||
|
||||
@@ -10,7 +10,7 @@ import type { IComputedValue } from "mobx";
|
||||
import type { CarouselProps } from "react-material-ui-carousel";
|
||||
import LegacyCarousel from "react-material-ui-carousel";
|
||||
import { Icon } from "../icon";
|
||||
import { slackUrl } from "../../../common/vars";
|
||||
import { forumsUrl } from "../../../common/vars";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import welcomeMenuItemsInjectable from "./welcome-menu-items/welcome-menu-items.injectable";
|
||||
import type { WelcomeMenuRegistration } from "./welcome-menu-items/welcome-menu-registration";
|
||||
@@ -93,12 +93,12 @@ const NonInjectedWelcome = observer(({
|
||||
<br />
|
||||
{"If you have any questions or feedback, please join our "}
|
||||
<a
|
||||
href={slackUrl}
|
||||
href={forumsUrl}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="link"
|
||||
>
|
||||
Lens Community slack channel
|
||||
Lens Forums
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
@@ -9,7 +9,7 @@ import type { ErrorInfo } from "react";
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { Button } from "../button";
|
||||
import { issuesTrackerUrl, slackUrl } from "../../../common/vars";
|
||||
import { issuesTrackerUrl, forumsUrl } from "../../../common/vars";
|
||||
import type { SingleOrMany } from "../../utils";
|
||||
import type { ObservableHistory } from "mobx-observable-history";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
@@ -53,15 +53,15 @@ class NonInjectedErrorBoundary extends React.Component<ErrorBoundaryProps & Depe
|
||||
</h5>
|
||||
<p>
|
||||
|
||||
{"To help us improve the product please report bugs to "}
|
||||
{"To help us improve the product please report bugs on"}
|
||||
<a
|
||||
href={slackUrl}
|
||||
href={forumsUrl}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Slack
|
||||
Lens Forums
|
||||
</a>
|
||||
{" community or "}
|
||||
{" or on our"}
|
||||
<a
|
||||
href={issuesTrackerUrl}
|
||||
rel="noreferrer"
|
||||
|
||||
+2
-2
@@ -19,8 +19,8 @@ import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-create
|
||||
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
|
||||
import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable";
|
||||
import createClusterInjectable from "../../../main/create-cluster/create-cluster.injectable";
|
||||
import type { PodStore } from "../+workloads-pods/store";
|
||||
import { createClusterInjectionToken } from "../../../common/cluster/create-cluster-injection-token";
|
||||
|
||||
describe("kube-object-list-layout", () => {
|
||||
let di: DiContainer;
|
||||
@@ -34,7 +34,7 @@ describe("kube-object-list-layout", () => {
|
||||
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
|
||||
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||
|
||||
const createCluster = di.inject(createClusterInjectable);
|
||||
const createCluster = di.inject(createClusterInjectionToken);
|
||||
|
||||
di.override(hostedClusterInjectable, () => createCluster({
|
||||
contextName: "some-context-name",
|
||||
|
||||
@@ -5,19 +5,16 @@
|
||||
import "./components/app.scss";
|
||||
|
||||
import { bootstrap } from "./bootstrap";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
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";
|
||||
|
||||
interface AppConfig {
|
||||
di: DiContainer;
|
||||
mode: string;
|
||||
}
|
||||
|
||||
export function createApp(conf: AppConfig) {
|
||||
const { di, mode } = conf;
|
||||
export const createApplication: CreateApplication = (config) => {
|
||||
const { mode } = config;
|
||||
const di = getDi();
|
||||
|
||||
runInAction(() => {
|
||||
di.register(getInjectable({
|
||||
@@ -25,10 +22,12 @@ export function createApp(conf: AppConfig) {
|
||||
instantiate: () => mode,
|
||||
injectionToken: nodeEnvInjectionToken,
|
||||
}));
|
||||
|
||||
registerInjectables(di);
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
start: () => bootstrap(di),
|
||||
di,
|
||||
};
|
||||
}
|
||||
};
|
||||
-2
@@ -12,7 +12,6 @@ import emitAppEventInjectable from "../../../../common/app-event-bus/emit-event.
|
||||
import loadExtensionsInjectable from "../../load-extensions.injectable";
|
||||
import loggerInjectable from "../../../../common/logger.injectable";
|
||||
import showErrorNotificationInjectable from "../../../components/notifications/show-error-notification.injectable";
|
||||
import closeRendererLogFileInjectable from "../../../logger/close-renderer-log-file.injectable";
|
||||
|
||||
const initClusterFrameInjectable = getInjectable({
|
||||
id: "init-cluster-frame",
|
||||
@@ -30,7 +29,6 @@ const initClusterFrameInjectable = getInjectable({
|
||||
emitAppEvent: di.inject(emitAppEventInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
showErrorNotification: di.inject(showErrorNotificationInjectable),
|
||||
closeFileLogging: di.inject(closeRendererLogFileInjectable),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
+3
-9
@@ -2,7 +2,6 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { once } from "lodash";
|
||||
import type { Cluster } from "../../../../common/cluster/cluster";
|
||||
import type { CatalogEntityRegistry } from "../../../api/catalog/entity/registry";
|
||||
import type { ShowNotification } from "../../../components/notifications";
|
||||
@@ -19,7 +18,6 @@ interface Dependencies {
|
||||
emitAppEvent: EmitAppEvent;
|
||||
logger: Logger;
|
||||
showErrorNotification: ShowNotification;
|
||||
closeFileLogging: () => void;
|
||||
}
|
||||
|
||||
const logPrefix = "[CLUSTER-FRAME]:";
|
||||
@@ -32,7 +30,6 @@ export const initClusterFrame = ({
|
||||
emitAppEvent,
|
||||
logger,
|
||||
showErrorNotification,
|
||||
closeFileLogging,
|
||||
}: Dependencies) =>
|
||||
async (unmountRoot: () => void) => {
|
||||
// TODO: Make catalogEntityRegistry already initialized when passed as dependency
|
||||
@@ -76,14 +73,11 @@ export const initClusterFrame = ({
|
||||
});
|
||||
});
|
||||
|
||||
const onCloseFrame = once(() => {
|
||||
window.onbeforeunload = () => {
|
||||
logger.info(
|
||||
`${logPrefix} Unload dashboard, clusterId=${(hostedCluster.id)}, frameId=${frameRoutingId}`,
|
||||
);
|
||||
closeFileLogging();
|
||||
unmountRoot();
|
||||
});
|
||||
|
||||
window.addEventListener("beforeunload", onCloseFrame);
|
||||
window.addEventListener("pagehide", onCloseFrame);
|
||||
unmountRoot();
|
||||
};
|
||||
};
|
||||
@@ -13,7 +13,6 @@ import loggerInjectable from "../../../common/logger.injectable";
|
||||
import { delay } from "../../../common/utils";
|
||||
import { broadcastMessage } from "../../../common/ipc";
|
||||
import { bundledExtensionsLoaded } from "../../../common/ipc/extension-handling";
|
||||
import closeRendererLogFileInjectable from "../../logger/close-renderer-log-file.injectable";
|
||||
|
||||
const initRootFrameInjectable = getInjectable({
|
||||
id: "init-root-frame",
|
||||
@@ -25,7 +24,6 @@ const initRootFrameInjectable = getInjectable({
|
||||
const lensProtocolRouterRenderer = di.inject(lensProtocolRouterRendererInjectable);
|
||||
const catalogEntityRegistry = di.inject(catalogEntityRegistryInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
const closeRendererLogFile = di.inject(closeRendererLogFileInjectable);
|
||||
|
||||
return async (unmountRoot: () => void) => {
|
||||
catalogEntityRegistry.init();
|
||||
@@ -61,7 +59,7 @@ const initRootFrameInjectable = getInjectable({
|
||||
|
||||
window.addEventListener("beforeunload", () => {
|
||||
logger.info("[ROOT-FRAME]: Unload app");
|
||||
closeRendererLogFile();
|
||||
|
||||
unmountRoot();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -4,15 +4,17 @@
|
||||
*/
|
||||
|
||||
import { createContainer } from "@ogre-tools/injectable";
|
||||
import { runInAction } from "mobx";
|
||||
import applicationInformationInjectable from "../common/vars/application-information-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 di = createContainer("renderer");
|
||||
const environment = "renderer";
|
||||
const di = createContainer(environment);
|
||||
|
||||
runInAction(() => {
|
||||
di.register(applicationInformationInjectable);
|
||||
});
|
||||
registerMobX(di);
|
||||
registerInjectableReact(di);
|
||||
setLegacyGlobalDiForExtensionApi(di, environment);
|
||||
|
||||
return di;
|
||||
};
|
||||
@@ -4,9 +4,7 @@
|
||||
*/
|
||||
|
||||
import { noop, chunk } from "lodash/fp";
|
||||
import type { Injectable } 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 { 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";
|
||||
@@ -14,44 +12,29 @@ import hostedClusterIdInjectable from "./cluster-frame-context/hosted-cluster-id
|
||||
import { runInAction } from "mobx";
|
||||
import requestAnimationFrameInjectable from "./components/animate/request-animation-frame.injectable";
|
||||
import startTopbarStateSyncInjectable from "./components/layout/top-bar/start-state-sync.injectable";
|
||||
import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx";
|
||||
import watchHistoryStateInjectable from "./remote-helpers/watch-history-state.injectable";
|
||||
import legacyOnChannelListenInjectable from "./ipc/legacy-channel-listen.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";
|
||||
import { getDi } from "./getDi";
|
||||
|
||||
export const getDiForUnitTesting = (
|
||||
opts: { doGeneralOverrides?: boolean } = {},
|
||||
) => {
|
||||
const { doGeneralOverrides = false } = opts;
|
||||
|
||||
const di = createContainer("renderer");
|
||||
|
||||
di.register(getInjectable({
|
||||
id: "node-env",
|
||||
instantiate: () => "production",
|
||||
injectionToken: nodeEnvInjectionToken,
|
||||
}));
|
||||
const di = getDi();
|
||||
|
||||
di.preventSideEffects();
|
||||
|
||||
setLegacyGlobalDiForExtensionApi(di, Environments.renderer);
|
||||
|
||||
const injectables = (
|
||||
global.injectablePaths.renderer.paths
|
||||
runInAction(() => {
|
||||
const injectables = global.injectablePaths.renderer.paths
|
||||
.map(path => require(path))
|
||||
.flatMap(Object.values)
|
||||
.filter(isInjectable)
|
||||
) as Injectable<any, any, any>[];
|
||||
.filter(isInjectable);
|
||||
|
||||
runInAction(() => {
|
||||
registerMobX(di);
|
||||
di.register(applicationInformationInjectable);
|
||||
|
||||
chunk(100)(injectables).forEach((chunkInjectables) => {
|
||||
di.register(...chunkInjectables);
|
||||
});
|
||||
for (const block of chunk(100)(injectables)) {
|
||||
di.register(...block);
|
||||
}
|
||||
});
|
||||
|
||||
if (doGeneralOverrides) {
|
||||
|
||||
@@ -14,4 +14,5 @@ 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 { createApp } from "./create-app";
|
||||
export { createApplication } from "./create-app";
|
||||
export type { CreateApplication, Application, ApplicationConfig } from "../common/create-app";
|
||||
@@ -1,22 +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 winstonLoggerInjectable from "../../common/winston-logger.injectable";
|
||||
import rendererFileLoggerTransportInjectable from "./file-transport.injectable";
|
||||
|
||||
const closeRendererLogFileInjectable = getInjectable({
|
||||
id: "close-renderer-log-file",
|
||||
instantiate: (di) => {
|
||||
const winstonLogger = di.inject(winstonLoggerInjectable);
|
||||
const fileLoggingTransport = di.inject(rendererFileLoggerTransportInjectable);
|
||||
|
||||
return () => {
|
||||
fileLoggingTransport.close?.();
|
||||
winstonLogger.remove(fileLoggingTransport);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default closeRendererLogFileInjectable;
|
||||
@@ -1,44 +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 { transports } from "winston";
|
||||
import directoryForLogsInjectable from "../../common/app-paths/directory-for-logs.injectable";
|
||||
import { loggerTransportInjectionToken } from "../../common/logger/transports";
|
||||
import windowLocationInjectable from "../../common/k8s-api/window-location.injectable";
|
||||
import currentlyInClusterFrameInjectable from "../routes/currently-in-cluster-frame.injectable";
|
||||
import { getClusterIdFromHost } from "../utils";
|
||||
|
||||
const rendererFileLoggerTransportInjectable = getInjectable({
|
||||
id: "renderer-file-logger-transport",
|
||||
instantiate: (di) => {
|
||||
let frameId: string;
|
||||
|
||||
const currentlyInClusterFrame = di.inject(
|
||||
currentlyInClusterFrameInjectable,
|
||||
);
|
||||
|
||||
if (currentlyInClusterFrame) {
|
||||
const { host } = di.inject(windowLocationInjectable);
|
||||
const clusterId = getClusterIdFromHost(host);
|
||||
|
||||
frameId = clusterId ? `cluster-${clusterId}` : "cluster";
|
||||
} else {
|
||||
frameId = "main";
|
||||
}
|
||||
|
||||
return new transports.File({
|
||||
handleExceptions: false,
|
||||
level: "info",
|
||||
filename: `lens-renderer-${frameId}.log`,
|
||||
dirname: di.inject(directoryForLogsInjectable),
|
||||
maxsize: 1024 * 1024,
|
||||
maxFiles: 2,
|
||||
tailable: true,
|
||||
});
|
||||
},
|
||||
injectionToken: loggerTransportInjectionToken,
|
||||
});
|
||||
|
||||
export default rendererFileLoggerTransportInjectable;
|
||||
@@ -5,19 +5,14 @@
|
||||
|
||||
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.renderer);
|
||||
|
||||
runInAction(() => {
|
||||
registerMobX(di);
|
||||
|
||||
autoRegister({
|
||||
di,
|
||||
requireContexts: [
|
||||
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),
|
||||
@@ -25,6 +20,4 @@ export function registerInjectables(di: DiContainer) {
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
return di;
|
||||
}
|
||||
@@ -4,6 +4,10 @@
|
||||
"version": "0.0.1",
|
||||
"description": "Jest configuration and scripts for Lens packages.",
|
||||
"type": "commonjs",
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/lensapp/lens.git"
|
||||
@@ -15,9 +19,6 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/lensapp/lens",
|
||||
"bin": {
|
||||
"lens-test": "bin/test.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@swc/core": "^1.3.20",
|
||||
"@swc/jest": "^0.2.23",
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
"version": "0.0.1",
|
||||
"description": "Typescript configuration for Lens packages.",
|
||||
"type": "commonjs",
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/lensapp/lens.git"
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
set -e
|
||||
webpack $@
|
||||
@@ -1 +0,0 @@
|
||||
rm -rfv build
|
||||
@@ -4,6 +4,10 @@
|
||||
"version": "0.0.1",
|
||||
"description": "Webpack configurations and scripts for Lens packages.",
|
||||
"type": "commonjs",
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/lensapp/lens.git"
|
||||
@@ -15,16 +19,13 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/lensapp/lens",
|
||||
"bin": {
|
||||
"lens-build": "bin/build.sh",
|
||||
"lens-remove-build": "bin/remove-build.sh"
|
||||
},
|
||||
"scripts": {
|
||||
"test:unit": "lens-test"
|
||||
"test:unit": "jest --coverage --runInBand"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/webpack-env": "^1.18.0",
|
||||
"css-loader": "^6.7.2",
|
||||
"fork-ts-checker-webpack-plugin": "^7.3.0",
|
||||
"mini-css-extract-plugin": "^2.7.0",
|
||||
"sass-loader": "^13.2.0",
|
||||
"style-loader": "^3.3.1",
|
||||
|
||||
+226
@@ -0,0 +1,226 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`get-multi-export-config given maximal package.json, when creating configuration works 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"entry": Object {
|
||||
"index": "./index.ts",
|
||||
},
|
||||
"externals": Array [
|
||||
[Function],
|
||||
[Function],
|
||||
],
|
||||
"externalsPresets": Object {
|
||||
"node": true,
|
||||
},
|
||||
"mode": "production",
|
||||
"module": Object {
|
||||
"rules": Array [
|
||||
Object {
|
||||
"loader": "ts-loader",
|
||||
"test": /\\\\\\.ts\\(x\\)\\?\\$/,
|
||||
},
|
||||
],
|
||||
},
|
||||
"name": "./index.ts",
|
||||
"node": Object {
|
||||
"__dirname": true,
|
||||
"__filename": true,
|
||||
},
|
||||
"output": Object {
|
||||
"filename": [Function],
|
||||
"libraryTarget": "commonjs2",
|
||||
"path": "/some-working-directory/dist",
|
||||
},
|
||||
"performance": Object {
|
||||
"hints": "error",
|
||||
"maxEntrypointSize": 100000,
|
||||
},
|
||||
"plugins": Array [
|
||||
ForkTsCheckerWebpackPlugin {
|
||||
"options": Object {
|
||||
"typescript": Object {
|
||||
"configOverwrite": Object {
|
||||
"compilerOptions": Object {
|
||||
"declaration": true,
|
||||
"declarationDir": "/some-working-directory/dist",
|
||||
},
|
||||
"include": Array [
|
||||
"./index.ts",
|
||||
],
|
||||
},
|
||||
"mode": "write-dts",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"resolve": Object {
|
||||
"extensions": Array [
|
||||
".ts",
|
||||
".tsx",
|
||||
],
|
||||
},
|
||||
"target": "node",
|
||||
},
|
||||
Object {
|
||||
"entry": Object {
|
||||
"index": "./some-entrypoint/index.ts",
|
||||
},
|
||||
"externals": Array [
|
||||
[Function],
|
||||
[Function],
|
||||
],
|
||||
"externalsPresets": Object {
|
||||
"node": true,
|
||||
},
|
||||
"mode": "production",
|
||||
"module": Object {
|
||||
"rules": Array [
|
||||
Object {
|
||||
"loader": "ts-loader",
|
||||
"test": /\\\\\\.ts\\(x\\)\\?\\$/,
|
||||
},
|
||||
],
|
||||
},
|
||||
"name": "./some-entrypoint/index.ts",
|
||||
"node": Object {
|
||||
"__dirname": true,
|
||||
"__filename": true,
|
||||
},
|
||||
"output": Object {
|
||||
"filename": [Function],
|
||||
"libraryTarget": "commonjs2",
|
||||
"path": "/some-working-directory/dist/some-entrypoint",
|
||||
},
|
||||
"performance": Object {
|
||||
"hints": "error",
|
||||
"maxEntrypointSize": 100000,
|
||||
},
|
||||
"plugins": Array [
|
||||
ForkTsCheckerWebpackPlugin {
|
||||
"options": Object {
|
||||
"typescript": Object {
|
||||
"configOverwrite": Object {
|
||||
"compilerOptions": Object {
|
||||
"declaration": true,
|
||||
"declarationDir": "/some-working-directory/dist/some-entrypoint",
|
||||
},
|
||||
"include": Array [
|
||||
"./some-entrypoint/index.ts",
|
||||
],
|
||||
},
|
||||
"mode": "write-dts",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"resolve": Object {
|
||||
"extensions": Array [
|
||||
".ts",
|
||||
".tsx",
|
||||
],
|
||||
},
|
||||
"target": "node",
|
||||
},
|
||||
Object {
|
||||
"entry": Object {
|
||||
"index": "./some-other-entrypoint/index.ts",
|
||||
},
|
||||
"externals": Array [
|
||||
[Function],
|
||||
[Function],
|
||||
],
|
||||
"externalsPresets": Object {
|
||||
"node": true,
|
||||
},
|
||||
"mode": "production",
|
||||
"module": Object {
|
||||
"rules": Array [
|
||||
Object {
|
||||
"loader": "ts-loader",
|
||||
"test": /\\\\\\.ts\\(x\\)\\?\\$/,
|
||||
},
|
||||
Object {
|
||||
"test": /\\\\\\.s\\?css\\$/,
|
||||
"use": Array [
|
||||
Object {
|
||||
"some": "miniCssExtractPluginLoader",
|
||||
},
|
||||
Object {
|
||||
"loader": "css-loader",
|
||||
"options": Object {
|
||||
"modules": Object {
|
||||
"auto": /\\\\\\.module\\\\\\./i,
|
||||
"localIdentName": "[name]__[local]--[hash:base64:5]",
|
||||
"mode": "local",
|
||||
},
|
||||
"sourceMap": false,
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"loader": "sass-loader",
|
||||
"options": Object {
|
||||
"sourceMap": false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
"name": "./some-other-entrypoint/index.ts",
|
||||
"node": Object {
|
||||
"__dirname": true,
|
||||
"__filename": true,
|
||||
},
|
||||
"output": Object {
|
||||
"filename": [Function],
|
||||
"libraryTarget": "commonjs2",
|
||||
"path": "/some-working-directory/dist/some-other-entrypoint",
|
||||
},
|
||||
"performance": Object {
|
||||
"hints": "error",
|
||||
"maxEntrypointSize": 100000,
|
||||
},
|
||||
"plugins": Array [
|
||||
ForkTsCheckerWebpackPlugin {
|
||||
"options": Object {
|
||||
"typescript": Object {
|
||||
"configOverwrite": Object {
|
||||
"compilerOptions": Object {
|
||||
"declaration": true,
|
||||
"declarationDir": "/some-working-directory/dist/some-other-entrypoint",
|
||||
},
|
||||
"include": Array [
|
||||
"./some-other-entrypoint/index.ts",
|
||||
],
|
||||
},
|
||||
"mode": "write-dts",
|
||||
},
|
||||
},
|
||||
},
|
||||
MiniCssExtractPlugin {
|
||||
"_sortedModulesCache": WeakMap {},
|
||||
"options": Object {
|
||||
"chunkFilename": "[name].css",
|
||||
"experimentalUseImportModule": undefined,
|
||||
"filename": "[name].css",
|
||||
"ignoreOrder": false,
|
||||
"runtime": true,
|
||||
},
|
||||
"runtimeOptions": Object {
|
||||
"attributes": undefined,
|
||||
"insert": undefined,
|
||||
"linkType": "text/css",
|
||||
},
|
||||
},
|
||||
],
|
||||
"resolve": Object {
|
||||
"extensions": Array [
|
||||
".ts",
|
||||
".tsx",
|
||||
],
|
||||
},
|
||||
"target": "node",
|
||||
},
|
||||
]
|
||||
`;
|
||||
@@ -1,5 +1,5 @@
|
||||
const nodeConfig = require("./node-config");
|
||||
const reactConfig = require("./react-config");
|
||||
const getNodeConfig = require("./get-node-config");
|
||||
const getReactConfigFor = require("./get-react-config");
|
||||
const path = require("path");
|
||||
const {
|
||||
map,
|
||||
@@ -14,7 +14,15 @@ const {
|
||||
} = require("lodash/fp");
|
||||
const { pipeline } = require("@ogre-tools/fp");
|
||||
|
||||
module.exports = (packageJson, dependencies = { nodeConfig, reactConfig }) => {
|
||||
module.exports = (
|
||||
packageJson,
|
||||
|
||||
dependencies = {
|
||||
resolvePath: path.resolve,
|
||||
workingDirectory: process.cwd(),
|
||||
getReactConfig: getReactConfigFor()
|
||||
}
|
||||
) => {
|
||||
if (!packageJson.lensMultiExportConfig) {
|
||||
throw new Error(
|
||||
`Tried to get multi export config for package "${packageJson.name}" but configuration is missing.`
|
||||
@@ -72,15 +80,20 @@ module.exports = (packageJson, dependencies = { nodeConfig, reactConfig }) => {
|
||||
);
|
||||
}
|
||||
|
||||
const toExportSpecificWebpackConfig =
|
||||
toExportSpecificWebpackConfigFor(dependencies);
|
||||
|
||||
return pipeline(
|
||||
packageJson.lensMultiExportConfig,
|
||||
toPairs,
|
||||
map(toExportSpecificWebpackConfigFor(dependencies))
|
||||
map(toExportSpecificWebpackConfig)
|
||||
);
|
||||
};
|
||||
|
||||
const toExpectedExport = (externalImportPath) => {
|
||||
const entrypointPath = `./${path.join(
|
||||
const posixJoinForPackageJson = path.posix.join;
|
||||
|
||||
const entrypointPath = `./${posixJoinForPackageJson(
|
||||
"./dist",
|
||||
externalImportPath,
|
||||
"index.js"
|
||||
@@ -89,7 +102,11 @@ const toExpectedExport = (externalImportPath) => {
|
||||
return [
|
||||
externalImportPath,
|
||||
{
|
||||
types: `./${path.join("./dist", externalImportPath, "index.d.ts")}`,
|
||||
types: `./${posixJoinForPackageJson(
|
||||
"./dist",
|
||||
externalImportPath,
|
||||
"index.d.ts"
|
||||
)}`,
|
||||
|
||||
default: entrypointPath,
|
||||
import: entrypointPath,
|
||||
@@ -101,20 +118,19 @@ const toExpectedExport = (externalImportPath) => {
|
||||
const toExportSpecificWebpackConfigFor =
|
||||
(dependencies) =>
|
||||
([externalImportPath, { buildType, entrypoint }]) => {
|
||||
const baseConfig =
|
||||
buildType === "node" ? dependencies.nodeConfig : dependencies.reactConfig;
|
||||
const outputDirectory = dependencies.resolvePath(
|
||||
dependencies.workingDirectory,
|
||||
"dist",
|
||||
externalImportPath
|
||||
);
|
||||
|
||||
return {
|
||||
...baseConfig,
|
||||
name: entrypoint,
|
||||
|
||||
entry: {
|
||||
index: entrypoint,
|
||||
},
|
||||
|
||||
output: {
|
||||
...baseConfig.output,
|
||||
path: path.join(baseConfig.output.path, externalImportPath),
|
||||
},
|
||||
};
|
||||
return buildType === "node"
|
||||
? getNodeConfig({
|
||||
entrypointFilePath: entrypoint,
|
||||
outputDirectory,
|
||||
})
|
||||
: dependencies.getReactConfig({
|
||||
entrypointFilePath: entrypoint,
|
||||
outputDirectory,
|
||||
});
|
||||
};
|
||||
Loaded 100 of 136 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user