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

chore: Improve linting within @k8slens/core

- Turning on @typescript-eslint/recommended-requiring-type-checking
- Turning off @typescript-eslint/no-unnecessary-type-assertion (due too many false positives)
- Making @typescript-eslint/no-explicit-any an error (except in tests)

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2023-05-01 13:48:32 -04:00
parent 6184c2f03b
commit fa44b795d4
734 changed files with 32216 additions and 4566 deletions

View File

@ -95,7 +95,7 @@ The properties of the `clusterPages` array objects are defined as follows:
- `id` is a string that identifies the page. - `id` is a string that identifies the page.
- `components` matches the `PageComponents` interface for which there is one field, `Page`. - `components` matches the `PageComponents` interface for which there is one field, `Page`.
- `Page` is of type ` React.ComponentType<any>`. - `Page` is of type ` React.ComponentType<Record<string, never>>`.
It offers flexibility in defining the appearance and behavior of your page. It offers flexibility in defining the appearance and behavior of your page.
`ExamplePage` in the example above can be defined in `page.tsx`: `ExamplePage` in the example above can be defined in `page.tsx`:
@ -304,7 +304,7 @@ The properties of the `globalPages` array objects are defined as follows:
- `id` is a string that identifies the page. - `id` is a string that identifies the page.
- `components` matches the `PageComponents` interface for which there is one field, `Page`. - `components` matches the `PageComponents` interface for which there is one field, `Page`.
- `Page` is of type `React.ComponentType<any>`. - `Page` is of type `React.ComponentType<Record<string, never>>`.
It offers flexibility in defining the appearance and behavior of your page. It offers flexibility in defining the appearance and behavior of your page.
`HelpPage` in the example above can be defined in `page.tsx`: `HelpPage` in the example above can be defined in `page.tsx`:

27983
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@ module.exports = {
"**/static/**/*", "**/static/**/*",
"**/site/**/*", "**/site/**/*",
"**/build/webpack/**/*", "**/build/webpack/**/*",
"**/webpack/**/*",
], ],
settings: { settings: {
react: { react: {
@ -106,6 +107,7 @@ module.exports = {
extends: [ extends: [
"eslint:recommended", "eslint:recommended",
"plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:react/recommended", "plugin:react/recommended",
"plugin:import/recommended", "plugin:import/recommended",
"plugin:import/typescript", "plugin:import/typescript",
@ -116,8 +118,8 @@ module.exports = {
"react-hooks", "react-hooks",
], ],
parserOptions: { parserOptions: {
ecmaVersion: 2018, project: true,
sourceType: "module", tsconfigRootDir: "./tsconfig.json",
}, },
rules: { rules: {
"no-constant-condition": ["error", { "no-constant-condition": ["error", {
@ -126,19 +128,14 @@ module.exports = {
"header/header": [2, "../../license-header"], "header/header": [2, "../../license-header"],
"react/prop-types": "off", "react/prop-types": "off",
"no-invalid-this": "off", "no-invalid-this": "off",
"@typescript-eslint/no-invalid-this": ["error"], "@typescript-eslint/no-invalid-this": "error",
"@typescript-eslint/explicit-function-return-type": "off", "@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/interface-name-prefix": "off", "@typescript-eslint/interface-name-prefix": "off",
"@typescript-eslint/no-use-before-define": "off", "@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-empty-interface": "off",
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/ban-ts-ignore": "off",
"@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-empty-function": "off", "@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-unused-vars": "off", "@typescript-eslint/no-unnecessary-type-assertion": "off",
"no-restricted-imports": ["error", { "no-restricted-imports": ["error", {
"paths": [ "paths": [
{ {
@ -186,6 +183,11 @@ module.exports = {
"named": "never", "named": "never",
"asyncArrow": "always", "asyncArrow": "always",
}], }],
"@typescript-eslint/restrict-template-expressions": ["error", {
"allowNumber": true,
"allowBoolean": true,
"allowNever": true,
}],
"@typescript-eslint/naming-convention": ["error", "@typescript-eslint/naming-convention": ["error",
{ {
"selector": "interface", "selector": "interface",
@ -217,7 +219,7 @@ module.exports = {
"ignoreRestSiblings": true, "ignoreRestSiblings": true,
}, },
], ],
"comman-dangle": "off", "comma-dangle": "off",
"@typescript-eslint/comma-dangle": ["error", "always-multiline"], "@typescript-eslint/comma-dangle": ["error", "always-multiline"],
"comma-spacing": "off", "comma-spacing": "off",
"@typescript-eslint/comma-spacing": "error", "@typescript-eslint/comma-spacing": "error",
@ -296,5 +298,19 @@ module.exports = {
}], }],
}, },
}, },
{
files: [
"**/*.test.ts",
"**/*.test.tsx",
],
plugins: [
"jest",
],
rules: {
"@typescript-eslint/unbound-method": "off",
"jest/unbound-method": "error",
"@typescript-eslint/no-unsafe-assignment": "off",
},
},
], ],
}; };

View File

@ -5,9 +5,7 @@
import type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/injectable";
import kubectlApplyAllInjectable from "../../main/kubectl/kubectl-apply-all.injectable"; import kubectlApplyAllInjectable from "../../main/kubectl/kubectl-apply-all.injectable";
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting"; import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
import type { KubernetesCluster } from "../catalog-entities"; import { 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 createResourceStackInjectable from "../k8s/create-resource-stack.injectable";
import appPathsStateInjectable from "../app-paths/app-paths-state.injectable"; import appPathsStateInjectable from "../app-paths/app-paths-state.injectable";
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable"; import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
@ -16,26 +14,35 @@ describe("create resource stack tests", () => {
let di: DiContainer; let di: DiContainer;
let cluster: KubernetesCluster; let cluster: KubernetesCluster;
beforeEach(async () => { beforeEach(() => {
di = getDiForUnitTesting(); di = getDiForUnitTesting();
cluster = { cluster = new KubernetesCluster({
getId: () => "test-cluster", metadata: {
} as any; labels: {},
name: "some-name",
uid: "test-cluster",
},
spec: {
kubeconfigContext: "some-context",
kubeconfigPath: "/some-kubeconfig-path",
},
status: {
phase: "some-phase",
},
});
di.override(readDirectoryInjectable, () => () => Promise.resolve(["file1"]) as any);
di.override(readFileInjectable, () => () => Promise.resolve("filecontents"));
di.override(appPathsStateInjectable, () => ({ di.override(appPathsStateInjectable, () => ({
get: () => ({}), get: () => ({}),
})); }));
di.override(directoryForUserDataInjectable, () => "/some-directory-for-user-data"); di.override(directoryForUserDataInjectable, () => "/some-directory-for-user-data");
}); });
describe("kubectlApplyFolder", () => { describe("kubectlApplyFolder", () => {
it("returns response", async () => { it("returns response", async () => {
di.override(kubectlApplyAllInjectable, () => () => Promise.resolve({ di.override(kubectlApplyAllInjectable, () => () => Promise.resolve({
callWasSuccessful: true as const, isOk: true as const,
response: "success", value: "success",
})); }));
const createResourceStack = di.inject(createResourceStackInjectable); const createResourceStack = di.inject(createResourceStackInjectable);
@ -48,7 +55,7 @@ describe("create resource stack tests", () => {
it("throws on error", async () => { it("throws on error", async () => {
di.override(kubectlApplyAllInjectable, () => () => Promise.resolve({ di.override(kubectlApplyAllInjectable, () => () => Promise.resolve({
callWasSuccessful: false as const, isOk: false as const,
error: "No permissions", error: "No permissions",
})); }));

View File

@ -4,6 +4,7 @@
*/ */
import { KubeConfig } from "@kubernetes/client-node"; import { KubeConfig } from "@kubernetes/client-node";
import assert from "assert";
import { validateKubeConfig, loadConfigFromString } from "../kube-helpers"; import { validateKubeConfig, loadConfigFromString } from "../kube-helpers";
const kubeconfig = ` const kubeconfig = `
@ -63,7 +64,7 @@ interface Kubeconfig {
}]; }];
kind: string; kind: string;
"current-context": string; "current-context": string;
preferences: {}; preferences: object;
} }
let mockKubeConfig: Kubeconfig; let mockKubeConfig: Kubeconfig;
@ -78,30 +79,33 @@ describe("kube helpers", () => {
describe("with default validation options", () => { describe("with default validation options", () => {
describe("with valid kubeconfig", () => { describe("with valid kubeconfig", () => {
it("does not return an error", () => { it("does not return an error", () => {
expect(validateKubeConfig(kc, "valid")).toBeDefined(); expect(validateKubeConfig(kc, "valid").isOk).toBe(true);
}); });
}); });
describe("with invalid context object", () => { describe("with invalid context object", () => {
it("returns an error", () => { it("returns an error", () => {
expect(validateKubeConfig(kc, "invalid").error?.toString()).toEqual( const result = validateKubeConfig(kc, "invalid");
expect.stringContaining("No valid context object provided in kubeconfig for context 'invalid'"),
); assert(result.isOk === false);
expect(result.error).toBe("No valid context object provided in kubeconfig for context 'invalid'");
}); });
}); });
describe("with invalid cluster object", () => { describe("with invalid cluster object", () => {
it("returns an error", () => { it("returns an error", () => {
expect(validateKubeConfig(kc, "invalidCluster").error?.toString()).toEqual( const result = validateKubeConfig(kc, "invalidCluster");
expect.stringContaining("No valid cluster object provided in kubeconfig for context 'invalidCluster'"),
); assert(result.isOk === false);
expect(result.error).toBe("No valid cluster object provided in kubeconfig for context 'invalidCluster'");
}); });
}); });
describe("with invalid user object", () => { describe("with invalid user object", () => {
it("returns an error", () => { it("returns an error", () => {
expect(validateKubeConfig(kc, "invalidUser").error?.toString()).toEqual( const result = validateKubeConfig(kc, "invalidUser");
expect.stringContaining("No valid user object provided in kubeconfig for context 'invalidUser'"),
); assert(result.isOk === false);
expect(result.error).toBe("No valid user object provided in kubeconfig for context 'invalidUser'");
}); });
}); });
}); });
@ -115,13 +119,15 @@ describe("kube helpers", () => {
describe("Check logger.error() output", () => { describe("Check logger.error() output", () => {
it("invalid yaml string", () => { it("invalid yaml string", () => {
const invalidYAMLString = "fancy foo config"; const invalidYAMLString = "fancy foo config";
const result = loadConfigFromString(invalidYAMLString);
expect(loadConfigFromString(invalidYAMLString).error).toBeInstanceOf(Error); expect(result.isOk).toBe(false);
}); });
it("empty contexts", () => { it("empty contexts", () => {
const emptyContexts = `apiVersion: v1\ncontexts: []`; const emptyContexts = `apiVersion: v1\ncontexts: []`;
const result = loadConfigFromString(emptyContexts);
expect(loadConfigFromString(emptyContexts).error).toBeUndefined(); expect(result.isOk).toBe(true);
}); });
}); });
@ -151,18 +157,20 @@ describe("kube helpers", () => {
}; };
}); });
it("single context is ok", async () => { it("single context is ok", () => {
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig)); const result = loadConfigFromString(JSON.stringify(mockKubeConfig));
expect(config.getCurrentContext()).toBe("minikube"); assert(result.isOk === true);
expect(result.value.getCurrentContext()).toBe("minikube");
}); });
it("multiple context is ok", async () => { it("multiple context is ok", () => {
mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "cluster-2" }, name: "cluster-2" }); mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "cluster-2" }, name: "cluster-2" });
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig)); const result = loadConfigFromString(JSON.stringify(mockKubeConfig));
expect(config.getCurrentContext()).toBe("minikube"); assert(result.isOk === true);
expect(config.contexts.length).toBe(2); expect(result.value.getCurrentContext()).toBe("minikube");
expect(result.value.contexts.length).toBe(2);
}); });
}); });
@ -192,43 +200,47 @@ describe("kube helpers", () => {
}; };
}); });
it("empty name in context causes it to be removed", async () => { it("empty name in context causes it to be removed", () => {
mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "cluster-2" }, name: "" }); mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "cluster-2" }, name: "" });
expect(mockKubeConfig.contexts.length).toBe(2); expect(mockKubeConfig.contexts.length).toBe(2);
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig)); const result = loadConfigFromString(JSON.stringify(mockKubeConfig));
expect(config.getCurrentContext()).toBe("minikube"); assert(result.isOk === true);
expect(config.contexts.length).toBe(1); expect(result.value.getCurrentContext()).toBe("minikube");
expect(result.value.contexts.length).toBe(1);
}); });
it("empty cluster in context causes it to be removed", async () => { it("empty cluster in context causes it to be removed", () => {
mockKubeConfig.contexts.push({ context: { cluster: "", user: "cluster-2" }, name: "cluster-2" }); mockKubeConfig.contexts.push({ context: { cluster: "", user: "cluster-2" }, name: "cluster-2" });
expect(mockKubeConfig.contexts.length).toBe(2); expect(mockKubeConfig.contexts.length).toBe(2);
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig)); const result = loadConfigFromString(JSON.stringify(mockKubeConfig));
expect(config.getCurrentContext()).toBe("minikube"); assert(result.isOk === true);
expect(config.contexts.length).toBe(1); expect(result.value.getCurrentContext()).toBe("minikube");
expect(result.value.contexts.length).toBe(1);
}); });
it("empty user in context causes it to be removed", async () => { it("empty user in context causes it to be removed", () => {
mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "" }, name: "cluster-2" }); mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "" }, name: "cluster-2" });
expect(mockKubeConfig.contexts.length).toBe(2); expect(mockKubeConfig.contexts.length).toBe(2);
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig)); const result = loadConfigFromString(JSON.stringify(mockKubeConfig));
expect(config.getCurrentContext()).toBe("minikube"); assert(result.isOk === true);
expect(config.contexts.length).toBe(1); expect(result.value.getCurrentContext()).toBe("minikube");
expect(result.value.contexts.length).toBe(1);
}); });
it("invalid context in between valid contexts is removed", async () => { it("invalid context in between valid contexts is removed", () => {
mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "" }, name: "cluster-2" }); mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "" }, name: "cluster-2" });
mockKubeConfig.contexts.push({ context: { cluster: "cluster-3", user: "cluster-3" }, name: "cluster-3" }); mockKubeConfig.contexts.push({ context: { cluster: "cluster-3", user: "cluster-3" }, name: "cluster-3" });
expect(mockKubeConfig.contexts.length).toBe(3); expect(mockKubeConfig.contexts.length).toBe(3);
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig)); const result = loadConfigFromString(JSON.stringify(mockKubeConfig));
expect(config.getCurrentContext()).toBe("minikube"); assert(result.isOk === true);
expect(config.contexts.length).toBe(2); expect(result.value.getCurrentContext()).toBe("minikube");
expect(config.contexts[0].name).toBe("minikube"); expect(result.value.contexts.length).toBe(2);
expect(config.contexts[1].name).toBe("cluster-3"); expect(result.value.contexts[0].name).toBe("minikube");
expect(result.value.contexts[1].name).toBe("cluster-3");
}); });
}); });
}); });

View File

@ -23,7 +23,7 @@ describe("user store tests", () => {
let resetTheme: ResetTheme; let resetTheme: ResetTheme;
let di: DiContainer; let di: DiContainer;
beforeEach(async () => { beforeEach(() => {
di = getDiForUnitTesting(); di = getDiForUnitTesting();
di.override(writeFileInjectable, () => () => Promise.resolve()); di.override(writeFileInjectable, () => () => Promise.resolve());
@ -55,7 +55,7 @@ describe("user store tests", () => {
expect(state.colorTheme).toBe("light"); expect(state.colorTheme).toBe("light");
}); });
it("correctly resets theme to default value", async () => { it("correctly resets theme to default value", () => {
state.colorTheme = "some other theme"; state.colorTheme = "some other theme";
resetTheme(); resetTheme();
expect(state.colorTheme).toBe(defaultThemeId); expect(state.colorTheme).toBe(defaultThemeId);

View File

@ -10,5 +10,5 @@ export interface AppEvent {
name: string; name: string;
action: string; action: string;
destination?: string; destination?: string;
params?: Record<string, any>; params?: Record<string, unknown>;
} }

View File

@ -38,7 +38,7 @@ describe("app-paths", () => {
sessionData: "/some-irrelevant-user-data", // By default this points to userData sessionData: "/some-irrelevant-user-data", // By default this points to userData
}; };
builder.beforeApplicationStart(({ mainDi }) => { await builder.beforeApplicationStart(({ mainDi }) => {
mainDi.override( mainDi.override(
getElectronAppPathInjectable, getElectronAppPathInjectable,
() => () =>
@ -120,7 +120,7 @@ describe("app-paths", () => {
let windowDi: DiContainer; let windowDi: DiContainer;
beforeEach(async () => { beforeEach(async () => {
builder.beforeApplicationStart(({ mainDi }) => { await builder.beforeApplicationStart(({ mainDi }) => {
mainDi.override( mainDi.override(
directoryForIntegrationTestingInjectable, directoryForIntegrationTestingInjectable,
() => "/some-integration-testing-app-data", () => "/some-integration-testing-app-data",

View File

@ -4,6 +4,12 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
interface NonWebpackRequire {
resolve(name: string): string;
}
declare const __non_webpack_require__: NonWebpackRequire;
const pathToNpmCliInjectable = getInjectable({ const pathToNpmCliInjectable = getInjectable({
id: "path-to-npm-cli", id: "path-to-npm-cli",
instantiate: () => __non_webpack_require__.resolve("npm"), instantiate: () => __non_webpack_require__.resolve("npm"),

View File

@ -19,7 +19,7 @@ export class GeneralEntity extends CatalogEntity<CatalogEntityMetadata, CatalogE
public readonly apiVersion = "entity.k8slens.dev/v1alpha1"; public readonly apiVersion = "entity.k8slens.dev/v1alpha1";
public readonly kind = "General"; public readonly kind = "General";
async onRun(context: CatalogEntityActionContext) { onRun(context: CatalogEntityActionContext) {
context.navigate(this.spec.path); context.navigate(this.spec.path);
} }
} }

View File

@ -55,8 +55,7 @@ export interface KubernetesClusterMetadata extends CatalogEntityMetadata {
*/ */
export type KubernetesClusterStatusPhase = "connected" | "connecting" | "disconnected" | "deleting"; export type KubernetesClusterStatusPhase = "connected" | "connecting" | "disconnected" | "deleting";
export interface KubernetesClusterStatus extends CatalogEntityStatus { export type KubernetesClusterStatus = CatalogEntityStatus;
}
export function isKubernetesCluster(item: unknown): item is KubernetesCluster { export function isKubernetesCluster(item: unknown): item is KubernetesCluster {
return item instanceof KubernetesCluster; return item instanceof KubernetesCluster;
@ -89,18 +88,10 @@ export class KubernetesCluster<
await requestClusterDeactivation(this.getId()); await requestClusterDeactivation(this.getId());
} }
async onRun(context: CatalogEntityActionContext) { onRun(context: CatalogEntityActionContext) {
context.navigate(`/cluster/${this.getId()}`); context.navigate(`/cluster/${this.getId()}`);
} }
onDetailsOpen(): void {
//
}
onSettingsOpen(): void {
//
}
onContextMenuOpen(context: CatalogEntityContextMenuContext) { onContextMenuOpen(context: CatalogEntityContextMenuContext) {
if (!this.metadata.source || this.metadata.source === "local") { if (!this.metadata.source || this.metadata.source === "local") {
context.menuItems.push({ context.menuItems.push({
@ -120,8 +111,8 @@ export class KubernetesCluster<
title: "Disconnect", title: "Disconnect",
icon: "link_off", icon: "link_off",
onClick: () => { onClick: () => {
this.disconnect(); void this.disconnect();
broadcastMessage( void broadcastMessage(
IpcRendererNavigationEvents.NAVIGATE_IN_APP, IpcRendererNavigationEvents.NAVIGATE_IN_APP,
"/catalog", "/catalog",
); );

View File

@ -26,7 +26,7 @@ export class WebLink extends CatalogEntity<CatalogEntityMetadata, WebLinkStatus,
public readonly apiVersion = WebLink.apiVersion; public readonly apiVersion = WebLink.apiVersion;
public readonly kind = WebLink.kind; public readonly kind = WebLink.kind;
async onRun() { onRun() {
window.open(this.spec.url, "_blank"); window.open(this.spec.url, "_blank");
} }

View File

@ -89,7 +89,7 @@ export interface CatalogCategorySpec {
/** /**
* If the filter return a thruthy value, the menu item is displayed * If the filter return a thruthy value, the menu item is displayed
*/ */
export type AddMenuFilter = (menu: CatalogEntityAddMenu) => any; export type AddMenuFilter = (menu: CatalogEntityAddMenu) => unknown;
export interface CatalogCategoryEvents { export interface CatalogCategoryEvents {
/** /**
@ -291,7 +291,7 @@ export interface CatalogEntitySettingsMenu {
group?: string; group?: string;
title: string; title: string;
components: { components: {
View: React.ComponentType<any>; View: React.ComponentType<Record<string, never>>;
}; };
} }
@ -323,7 +323,7 @@ export interface CatalogEntityAddMenuContext {
menuItems: CatalogEntityAddMenu[]; menuItems: CatalogEntityAddMenu[];
} }
export type CatalogEntitySpec = Record<string, any>; export type CatalogEntitySpec = Record<string, unknown>;
export interface CatalogEntityData< export interface CatalogEntityData<
@ -409,7 +409,17 @@ export abstract class CatalogEntity<
return this.status.enabled ?? true; return this.status.enabled ?? true;
} }
public onRun?(context: CatalogEntityActionContext): void | Promise<void>; public onRun(context: CatalogEntityActionContext): void | Promise<void> {
public onContextMenuOpen?(context: CatalogEntityContextMenuContext): void | Promise<void>; void context;
public onSettingsOpen?(context: CatalogEntitySettingsContext): void | Promise<void>; }
public onContextMenuOpen(context: CatalogEntityContextMenuContext): void | Promise<void> {
void context;
}
/**
* @deprecated This has never been used
*/
public onSettingsOpen(context: CatalogEntitySettingsContext): void | Promise<void> {
void context;
}
} }

View File

@ -3,13 +3,13 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { action, computed, observable, makeObservable } from "mobx"; import { action, computed, observable, makeObservable, runInAction } from "mobx";
import { once } from "lodash"; import { once } from "lodash";
import { iter, getOrInsertMap, strictSet } from "@k8slens/utilities"; import { iter, getOrInsertMap, strictSet } from "@k8slens/utilities";
import type { Disposer } from "@k8slens/utilities"; import type { Disposer } from "@k8slens/utilities";
import type { CatalogCategory, CatalogEntityData, CatalogEntityKindData } from "./catalog-entity"; import type { CatalogCategory, CatalogEntityData, CatalogEntityKindData } from "./catalog-entity";
export type CategoryFilter = (category: CatalogCategory) => any; export type CategoryFilter = (category: CatalogCategory) => unknown;
export class CatalogCategoryRegistry { export class CatalogCategoryRegistry {
protected readonly categories = observable.set<CatalogCategory>(); protected readonly categories = observable.set<CatalogCategory>();
@ -22,16 +22,18 @@ export class CatalogCategoryRegistry {
makeObservable(this); makeObservable(this);
} }
@action add(category: CatalogCategory): Disposer { add(category: CatalogCategory): Disposer {
const byGroup = getOrInsertMap(this.groupKinds, category.spec.group); return runInAction(() => {
const byGroup = getOrInsertMap(this.groupKinds, category.spec.group);
this.categories.add(category); this.categories.add(category);
strictSet(byGroup, category.spec.names.kind, category); strictSet(byGroup, category.spec.names.kind, category);
return () => { return action(() => {
this.categories.delete(category); this.categories.delete(category);
byGroup.delete(category.spec.names.kind); byGroup.delete(category.spec.names.kind);
}; });
});
} }
getById(id: string) { getById(id: string) {

View File

@ -54,7 +54,7 @@ export function getShortName(entity: CatalogEntity): string {
} }
export function getIconColourHash(entity: CatalogEntity): string { export function getIconColourHash(entity: CatalogEntity): string {
return `${entity.metadata.name}-${entity.metadata.source}`; return `${entity.metadata.name}-${entity.metadata.source ?? ""}`;
} }
export function getIconBackground(entity: CatalogEntity): string | undefined { export function getIconBackground(entity: CatalogEntity): string | undefined {

View File

@ -14,7 +14,7 @@ const visitEntityContextMenuInjectable = getInjectable({
const categoryRegistry = di.inject(catalogCategoryRegistryInjectable); const categoryRegistry = di.inject(catalogCategoryRegistryInjectable);
return (entity, context) => { return (entity, context) => {
entity.onContextMenuOpen?.(context); void entity.onContextMenuOpen(context);
categoryRegistry.getCategoryForEntity(entity)?.emit("contextMenuOpen", entity, context); categoryRegistry.getCategoryForEntity(entity)?.emit("contextMenuOpen", entity, context);
}; };
}, },

View File

@ -3,12 +3,12 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import Joi from "joi"; import { z } from "zod";
/** /**
* JSON serializable metadata type * JSON serializable metadata type
*/ */
export type ClusterMetadata = Record<string, string | number | boolean | object>; export type ClusterMetadata = Partial<Record<string, Metadata>>;
/** /**
* Metadata for cluster's prometheus settings * Metadata for cluster's prometheus settings
@ -29,31 +29,55 @@ export type ClusterId = string;
*/ */
export type UpdateClusterModel = Omit<ClusterModel, "id">; export type UpdateClusterModel = Omit<ClusterModel, "id">;
export type Literal = z.infer<typeof literalSchema>;
export const literalSchema = z.string().or(z.number()).or(z.boolean());
export type Metadata = Literal | { [key: string]: Metadata } | Metadata[];
export const metadataSchema: z.ZodType<Metadata> = z.lazy(() => z.union([literalSchema, z.array(metadataSchema), z.record(metadataSchema)]));
export const prometheusPreferencesSchema = z.object({
namespace: z.string(),
service: z.string(),
prefix: z.string(),
port: z.number(),
});
export const prometheusProviderPreferencesSchema = z.object({
type: z.string(),
});
export const preferencesSchema = z.object({
terminalCWD: z.string().min(1).optional(),
clusterName: z.string().min(1).optional(),
httpsProxy: z.string().min(1).optional(),
nodeShellImage: z.string().min(1).optional(),
imagePullSecret: z.string().min(1).optional(),
defaultNamespace: z.string().min(1).optional(),
iconOrder: z.number().optional(),
icon: z.nullable(z.string()).optional(),
hiddenMetrics: z.array(z.string()).optional(),
prometheus: prometheusPreferencesSchema.optional(),
prometheusProvider: prometheusProviderPreferencesSchema.optional(),
});
/** /**
* A type validator for `UpdateClusterModel` so that only expected types are present * A type validator for `UpdateClusterModel` so that only expected types are present
*/ */
export const updateClusterModelChecker = Joi.object<UpdateClusterModel>({ export const updateClusterModelSchema = z.object({
kubeConfigPath: Joi.string() kubeConfigPath: z.string().min(1),
.required() contextName: z.string().min(1),
.min(1), preferences: preferencesSchema.optional(),
contextName: Joi.string() metadata: z.record(metadataSchema).optional(),
.required() accessibleNamespaces: z.array(z.string()).optional(),
.min(1), labels: z.record(z.string()).optional(),
preferences: Joi.object(),
metadata: Joi.object(),
accessibleNamespaces: Joi.array()
.items(Joi.string()),
labels: Joi.object().pattern(Joi.string(), Joi.string()),
}); });
/** /**
* A type validator for just the `id` fields of `ClusterModel`. The rest is * A type validator for just the `id` fields of `ClusterModel`. The rest is
* covered by `updateClusterModelChecker` * covered by `updateClusterModelChecker`
*/ */
export const clusterModelIdChecker = Joi.object<Pick<ClusterModel, "id">>({ export const clusterModelIdSchema = z.object({
id: Joi.string() id: z.string().min(1),
.required()
.min(1),
}); });
/** /**
@ -85,7 +109,7 @@ export interface ClusterModel {
} }
/** /**
* This data is retreived from the kubeconfig file before calling the cluster constructor. * This data is retrieved from the kubeconfig file before calling the cluster constructor.
* *
* That is done to remove the external dependency on the construction of Cluster instances. * That is done to remove the external dependency on the construction of Cluster instances.
*/ */

View File

@ -6,10 +6,12 @@
import { computed, observable, toJS, runInAction } from "mobx"; import { computed, observable, toJS, runInAction } from "mobx";
import type { KubeApiResource } from "../rbac"; import type { KubeApiResource } from "../rbac";
import type { ClusterState, ClusterId, ClusterMetadata, ClusterModel, ClusterPreferences, ClusterPrometheusPreferences, UpdateClusterModel } from "../cluster-types"; import type { ClusterState, ClusterId, ClusterMetadata, ClusterModel, ClusterPreferences, ClusterPrometheusPreferences, UpdateClusterModel } from "../cluster-types";
import { ClusterMetadataKey, clusterModelIdChecker, updateClusterModelChecker } from "../cluster-types"; import { ClusterMetadataKey, clusterModelIdSchema, updateClusterModelSchema } from "../cluster-types";
import type { IObservableValue } from "mobx"; import type { IObservableValue } from "mobx";
import { replaceObservableObject } from "../utils/replace-observable-object"; import { replaceObservableObject } from "../utils/replace-observable-object";
import { pick } from "lodash"; import { pick } from "lodash";
import type { ZodError } from "zod";
import type { Result } from "@k8slens/utilities";
export class Cluster { export class Cluster {
/** /**
@ -20,12 +22,12 @@ export class Cluster {
/** /**
* Kubeconfig context name * Kubeconfig context name
*/ */
readonly contextName = observable.box() as IObservableValue<string>; readonly contextName: IObservableValue<string>;
/** /**
* Path to kubeconfig * Path to kubeconfig
*/ */
readonly kubeConfigPath = observable.box() as IObservableValue<string>; readonly kubeConfigPath: IObservableValue<string>;
/** /**
* Describes if we can detect that cluster is online * Describes if we can detect that cluster is online
@ -117,15 +119,58 @@ export class Cluster {
*/ */
readonly prometheusPreferences = computed(() => pick(toJS(this.preferences), "prometheus", "prometheusProvider") as ClusterPrometheusPreferences); readonly prometheusPreferences = computed(() => pick(toJS(this.preferences), "prometheus", "prometheusProvider") as ClusterPrometheusPreferences);
constructor({ id, ...model }: ClusterModel) { static create({ id, ...model }: ClusterModel): Result<Cluster, ZodError<unknown>> {
const { error } = clusterModelIdChecker.validate({ id }); const clusterIdResult = clusterModelIdSchema.safeParse({ id });
if (error) { if (!clusterIdResult.success) {
throw error; return {
isOk: false,
error: clusterIdResult.error,
};
} }
const updateModelResult = updateClusterModelSchema.safeParse(model);
if (!updateModelResult.success) {
return {
isOk: false,
error: updateModelResult.error,
};
}
return {
isOk: true,
value: new Cluster(clusterIdResult.data.id, updateModelResult.data),
};
}
static createForTestingOnly({ id, ...model }: ClusterModel): Cluster {
const clusterIdResult = clusterModelIdSchema.parse({ id });
const updateModelResult = updateClusterModelSchema.parse(model);
return new Cluster(clusterIdResult.id, updateModelResult);
}
private constructor(id: string, model: UpdateClusterModel) {
this.id = id; this.id = id;
this.updateModel(model); this.kubeConfigPath = observable.box(model.kubeConfigPath);
this.contextName = observable.box(model.contextName);
if (model.preferences) {
replaceObservableObject(this.preferences, model.preferences);
}
if (model.metadata) {
replaceObservableObject(this.metadata, model.metadata);
}
if (model.accessibleNamespaces) {
this.accessibleNamespaces.replace(model.accessibleNamespaces);
}
if (model.labels) {
replaceObservableObject(this.labels, model.labels);
}
} }
/** /**
@ -133,13 +178,14 @@ export class Cluster {
* *
* @param model * @param model
*/ */
updateModel(model: UpdateClusterModel) { updateModel(model: UpdateClusterModel): Result<Cluster, ZodError<unknown>> {
// Note: do not assign ID as that should never be updated const updateModelResult = updateClusterModelSchema.safeParse(model);
const { error } = updateClusterModelChecker.validate(model, { allowUnknown: true }); if (!updateModelResult.success) {
return {
if (error) { isOk: false,
throw error; error: updateModelResult.error,
};
} }
runInAction(() => { runInAction(() => {
@ -162,6 +208,11 @@ export class Cluster {
replaceObservableObject(this.labels, model.labels); replaceObservableObject(this.labels, model.labels);
} }
}); });
return {
isOk: true,
value: this,
};
} }
toJSON(): ClusterModel { toJSON(): ClusterModel {

View File

@ -31,7 +31,7 @@ const createCanIInjectable = getInjectable({
return body.status?.allowed ?? false; return body.status?.allowed ?? false;
} catch (error) { } catch (error) {
logger.error(`[AUTHORIZATION-REVIEW]: failed to create access review: ${error}`, { resourceAttributes }); logger.error(`[AUTHORIZATION-REVIEW]: failed to create access review: ${String(error)}`, { resourceAttributes });
return false; return false;
} }

View File

@ -32,7 +32,7 @@ const createRequestNamespaceListPermissionsInjectable = getInjectable({
}); });
if (!status || status.incomplete) { if (!status || status.incomplete) {
logger.warn(`[AUTHORIZATION-NAMESPACE-REVIEW]: allowing all resources in namespace="${namespace}" due to incomplete SelfSubjectRulesReview: ${status?.evaluationError}`); logger.warn(`[AUTHORIZATION-NAMESPACE-REVIEW]: allowing all resources in namespace="${namespace}" due to incomplete SelfSubjectRulesReview: ${status?.evaluationError ?? ""}`);
return () => true; return () => true;
} }

View File

@ -6,27 +6,17 @@ import type { KubeConfig } from "@kubernetes/client-node";
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import type { Cluster } from "./cluster"; import type { Cluster } from "./cluster";
import loadConfigFromFileInjectable from "../kube-helpers/load-config-from-file.injectable"; import loadConfigFromFileInjectable from "../kube-helpers/load-config-from-file.injectable";
import type { ConfigResult } from "../kube-helpers"; import type { AsyncResult } from "@k8slens/utilities";
import type { ZodError } from "zod";
export interface LoadKubeconfig { export type LoadKubeconfig = () => AsyncResult<KubeConfig, ZodError<unknown>>;
(fullResult?: false): Promise<KubeConfig>;
(fullResult: true): Promise<ConfigResult>;
}
const loadKubeconfigInjectable = getInjectable({ const loadKubeconfigInjectable = getInjectable({
id: "load-kubeconfig", id: "load-kubeconfig",
instantiate: (di, cluster) => { instantiate: (di, cluster) => {
const loadConfigFromFile = di.inject(loadConfigFromFileInjectable); const loadConfigFromFile = di.inject(loadConfigFromFileInjectable);
return (async (fullResult = false) => { return () => loadConfigFromFile(cluster.kubeConfigPath.get());
const result = await loadConfigFromFile(cluster.kubeConfigPath.get());
if (fullResult) {
return result;
}
return result.config;
}) as LoadKubeconfig;
}, },
lifecycle: lifecycleEnum.keyedSingleton({ lifecycle: lifecycleEnum.keyedSingleton({
getInstanceKey: (di, cluster: Cluster) => cluster.id, getInstanceKey: (di, cluster: Cluster) => cluster.id,

View File

@ -193,7 +193,7 @@ describe("requestNamespaceListPermissions", () => {
status, status,
spec: {}, spec: {},
}, },
response: null as unknown as IncomingMessage, value: null as unknown as IncomingMessage,
}); });
}); });

View File

@ -25,26 +25,26 @@ const downloadBinaryInjectable = getInjectable({
result = await fetch(url, opts as RequestInit); result = await fetch(url, opts as RequestInit);
} catch (error) { } catch (error) {
return { return {
callWasSuccessful: false, isOk: false,
error: String(error), error: String(error),
}; };
} }
if (result.status < 200 || 300 <= result.status) { if (result.status < 200 || 300 <= result.status) {
return { return {
callWasSuccessful: false, isOk: false,
error: result.statusText, error: result.statusText,
}; };
} }
try { try {
return { return {
callWasSuccessful: true, isOk: true,
response: await result.buffer(), value: await result.buffer(),
}; };
} catch (error) { } catch (error) {
return { return {
callWasSuccessful: false, isOk: false,
error: String(error), error: String(error),
}; };
} }

View File

@ -19,26 +19,26 @@ export const downloadJsonWith = (fetch: Fetch): DownloadJson => async (url, opts
result = await fetch(url, opts as RequestInit); result = await fetch(url, opts as RequestInit);
} catch (error) { } catch (error) {
return { return {
callWasSuccessful: false, isOk: false,
error: String(error), error: String(error),
}; };
} }
if (result.status < 200 || 300 <= result.status) { if (result.status < 200 || 300 <= result.status) {
return { return {
callWasSuccessful: false, isOk: false,
error: result.statusText, error: result.statusText,
}; };
} }
try { try {
return { return {
callWasSuccessful: true, isOk: true,
response: await result.json(), value: await result.json(),
}; };
} catch (error) { } catch (error) {
return { return {
callWasSuccessful: false, isOk: false,
error: String(error), error: String(error),
}; };
} }

View File

@ -18,9 +18,11 @@ type RequiredKeys<T> = Exclude<
type ObjectContainingNoRequired<T> = T extends void type ObjectContainingNoRequired<T> = T extends void
? never ? never
: RequiredKeys<T> extends [] : (
? any RequiredKeys<T> extends []
: never; ? Record<string, never>
: never
);
type ObjectContainsNoRequired<T> = T extends ObjectContainingNoRequired<T> type ObjectContainsNoRequired<T> = T extends ObjectContainingNoRequired<T>
? true ? true
@ -30,10 +32,12 @@ type ObjectContainsNoRequired<T> = T extends ObjectContainingNoRequired<T>
// - Navigating to route without parameters, with parameters // - Navigating to route without parameters, with parameters
// - Navigating to route with required parameters, without parameters // - Navigating to route with required parameters, without parameters
type Parameters<TParameters> = TParameters extends void type Parameters<TParameters> = TParameters extends void
? {} ? { parameters?: undefined }
: ObjectContainsNoRequired<TParameters> extends true : (
? { parameters?: TParameters } ObjectContainsNoRequired<TParameters> extends true
: { parameters: TParameters }; ? { parameters?: TParameters }
: { parameters: TParameters }
);
export type NavigateToRouteOptions<TRoute> = Parameters< export type NavigateToRouteOptions<TRoute> = Parameters<
InferParametersFrom<TRoute> InferParametersFrom<TRoute>

View File

@ -9,7 +9,7 @@ export interface NavigateToUrlOptions {
forceRootFrame?: boolean; forceRootFrame?: boolean;
} }
export type NavigateToUrl = (url: string, options?: NavigateToUrlOptions) => void; export type NavigateToUrl = (url: string, options?: NavigateToUrlOptions) => void | Promise<void>;
export const navigateToUrlInjectionToken = getInjectionToken<NavigateToUrl>( export const navigateToUrlInjectionToken = getInjectionToken<NavigateToUrl>(
{ id: "navigate-to-url-injection-token" }, { id: "navigate-to-url-injection-token" },

View File

@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
import type { ExecFileException, ExecFileOptions } from "child_process"; import type { ExecFileException, ExecFileOptions } from "child_process";
import { execFile } from "child_process"; import { execFile } from "child_process";
import type { AsyncResult } from "@k8slens/utilities"; import type { AsyncResult } from "@k8slens/utilities";
import { isArray } from "@k8slens/utilities";
export type ExecFileError = ExecFileException & { stderr: string }; export type ExecFileError = ExecFileException & { stderr: string };
@ -21,7 +22,7 @@ const execFileInjectable = getInjectable({
instantiate: (): ExecFile => { instantiate: (): ExecFile => {
return (filePath: string, argsOrOptions?: string[] | ExecFileOptions, maybeOptions?: ExecFileOptions) => { return (filePath: string, argsOrOptions?: string[] | ExecFileOptions, maybeOptions?: ExecFileOptions) => {
const { args, options } = (() => { const { args, options } = (() => {
if (Array.isArray(argsOrOptions)) { if (isArray(argsOrOptions)) {
return { return {
args: argsOrOptions, args: argsOrOptions,
options: maybeOptions ?? {}, options: maybeOptions ?? {},
@ -38,13 +39,13 @@ const execFileInjectable = getInjectable({
execFile(filePath, args, options, (error, stdout, stderr) => { execFile(filePath, args, options, (error, stdout, stderr) => {
if (error) { if (error) {
resolve({ resolve({
callWasSuccessful: false, isOk: false,
error: Object.assign(error, { stderr }), error: Object.assign(error, { stderr }),
}); });
} else { } else {
resolve({ resolve({
callWasSuccessful: true, isOk: true,
response: stdout, value: stdout,
}); });
} }
}); });

View File

@ -6,6 +6,7 @@
import { getGlobalOverride } from "@k8slens/test-utils"; import { getGlobalOverride } from "@k8slens/test-utils";
import extractTarInjectable from "./extract-tar.injectable"; import extractTarInjectable from "./extract-tar.injectable";
// eslint-disable-next-line @typescript-eslint/require-await
export default getGlobalOverride(extractTarInjectable, () => async () => { export default getGlobalOverride(extractTarInjectable, () => async () => {
throw new Error("tried to extract a tar file without override"); throw new Error("tried to extract a tar file without override");
}); });

View File

@ -3,9 +3,12 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { WriteFileOptions } from "fs";
import type { ReadOptions } from "fs-extra"; import type { ReadOptions } from "fs-extra";
import fse from "fs-extra"; import fse from "fs-extra";
export type FileSystemFunctions = ReturnType<(typeof fsInjectable)["instantiate"]>;
/** /**
* NOTE: Add corresponding override of this injectable 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`
*/ */
@ -40,13 +43,13 @@ const fsInjectable = getInjectable({
return { return {
readFile, readFile,
readJson: readJson as (file: string, options?: ReadOptions | BufferEncoding) => Promise<any>, readJson: readJson as (file: string, options?: ReadOptions | BufferEncoding) => Promise<unknown>,
writeFile, writeFile,
writeJson, writeJson: writeJson as (file: string, value: unknown, options?: string | WriteFileOptions) => Promise<void>,
pathExists, pathExists,
readdir, readdir,
readFileSync, readFileSync,
readJsonSync, readJsonSync: readJsonSync as (file: string, options?: ReadOptions | BufferEncoding) => unknown,
writeFileSync, writeFileSync,
writeJsonSync, writeJsonSync,
pathExistsSync, pathExistsSync,

View File

@ -3,10 +3,9 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { JsonValue } from "type-fest";
import fsInjectable from "./fs.injectable"; import fsInjectable from "./fs.injectable";
export type ReadJson = (filePath: string) => Promise<JsonValue>; export type ReadJson = (filePath: string) => Promise<unknown>;
const readJsonFileInjectable = getInjectable({ const readJsonFileInjectable = getInjectable({
id: "read-json-file", id: "read-json-file",

View File

@ -9,7 +9,7 @@ import type { Stats } from "fs-extra";
import { lowerFirst } from "lodash/fp"; import { lowerFirst } from "lodash/fp";
import statInjectable from "./stat.injectable"; import statInjectable from "./stat.injectable";
export type ValidateDirectory = (path: string) => AsyncResult<undefined>; export type ValidateDirectory = (path: string) => AsyncResult<undefined, string>;
function getUserReadableFileType(stats: Stats): string { function getUserReadableFileType(stats: Stats): string {
if (stats.isFile()) { if (stats.isFile()) {
@ -46,13 +46,13 @@ const validateDirectoryInjectable = getInjectable({
const stats = await stat(path); const stats = await stat(path);
if (stats.isDirectory()) { if (stats.isDirectory()) {
return { callWasSuccessful: true, response: undefined }; return { isOk: true, value: undefined };
} }
return { callWasSuccessful: false, error: `the provided path is ${getUserReadableFileType(stats)} and not a directory.` }; return { isOk: false, error: `the provided path is ${getUserReadableFileType(stats)} and not a directory.` };
} catch (error) { } catch (error) {
if (!isErrnoException(error)) { if (!isErrnoException(error)) {
return { callWasSuccessful: false, error: "of an unknown error, please try again." }; return { isOk: false, error: "of an unknown error, please try again." };
} }
const humanReadableErrors: Record<string, string> = { const humanReadableErrors: Record<string, string> = {
@ -67,7 +67,7 @@ const validateDirectoryInjectable = getInjectable({
? humanReadableErrors[error.code] ? humanReadableErrors[error.code]
: lowerFirst(String(error)); : lowerFirst(String(error));
return { callWasSuccessful: false, error: humanReadableError }; return { isOk: false, error: humanReadableError };
} }
}; };
}, },

View File

@ -12,6 +12,7 @@ import readJsonSyncInjectable from "../fs/read-json-sync.injectable";
import writeJsonSyncInjectable from "../fs/write-json-sync.injectable"; import writeJsonSyncInjectable from "../fs/write-json-sync.injectable";
import { get, has, set } from "lodash"; import { get, has, set } from "lodash";
import semver from "semver"; import semver from "semver";
import type { Options as ConfOptions } from "conf/dist/source/types";
const MIGRATION_KEY = `__internal__.migrations.version`; const MIGRATION_KEY = `__internal__.migrations.version`;
@ -43,16 +44,16 @@ export default getGlobalOverride(getConfigurationFileModelInjectable, (di) => {
const readJsonSync = di.inject(readJsonSyncInjectable); const readJsonSync = di.inject(readJsonSyncInjectable);
const writeJsonSync = di.inject(writeJsonSyncInjectable); const writeJsonSync = di.inject(writeJsonSyncInjectable);
return (options) => { return <T extends object>(options: ConfOptions<T>) => {
assert(options.cwd, "Missing options.cwd"); assert(options.cwd, "Missing options.cwd");
assert(options.configName, "Missing options.configName"); assert(options.configName, "Missing options.configName");
assert(options.projectVersion, "Missing options.projectVersion"); assert(options.projectVersion, "Missing options.projectVersion");
const configFilePath = path.posix.join(options.cwd, `${options.configName}.json`); const configFilePath = path.posix.join(options.cwd, `${options.configName}.json`);
let store: object = {}; let store: Partial<Record<string, unknown>> = {};
try { try {
store = readJsonSync(configFilePath); store = readJsonSync(configFilePath) as Partial<Record<string, unknown>>;
} catch { } catch {
// ignore // ignore
} }
@ -62,12 +63,12 @@ export default getGlobalOverride(getConfigurationFileModelInjectable, (di) => {
return store; return store;
}, },
path: configFilePath, path: configFilePath,
get: (key: string) => get(store, key), get: (key: string) => get(store, key) as unknown,
set: (key: string, value: unknown) => { set: (key: string, value: unknown) => {
let currentState: Partial<Record<string, unknown>>; let currentState: Partial<Record<string, unknown>>;
try { try {
currentState = readJsonSync(configFilePath); currentState = readJsonSync(configFilePath) as Partial<Record<string, unknown>>;
} catch { } catch {
currentState = {}; currentState = {};
} }
@ -76,13 +77,13 @@ export default getGlobalOverride(getConfigurationFileModelInjectable, (di) => {
...currentState, ...currentState,
[key]: value, [key]: value,
}); });
store = readJsonSync(configFilePath); store = readJsonSync(configFilePath) as Partial<Record<string, unknown>>;
}, },
delete: (key: string) => { delete: (key: string) => {
let currentState: Partial<Record<string, unknown>>; let currentState: Partial<Record<string, unknown>>;
try { try {
currentState = readJsonSync(configFilePath); currentState = readJsonSync(configFilePath) as Partial<Record<string, unknown>>;
} catch { } catch {
currentState = {}; currentState = {};
} }
@ -90,20 +91,20 @@ export default getGlobalOverride(getConfigurationFileModelInjectable, (di) => {
delete currentState[key]; delete currentState[key];
writeJsonSync(configFilePath, currentState); writeJsonSync(configFilePath, currentState);
store = readJsonSync(configFilePath); store = readJsonSync(configFilePath) as Partial<Record<string, unknown>>;
}, },
has: (key: string) => has(store, key), has: (key: string) => has(store, key),
clear: () => { clear: () => {
writeJsonSync(configFilePath, {}); writeJsonSync(configFilePath, {});
store = readJsonSync(configFilePath); store = readJsonSync(configFilePath) as Partial<Record<string, unknown>>;
}, },
} as Partial<Config> as Config<any>; } as Partial<Config> as Config<T>;
// Migrate // Migrate
{ {
const migrations = options.migrations ?? []; const migrations = options.migrations ?? [];
const versionToMigrate = options.projectVersion; const versionToMigrate = options.projectVersion;
let previousMigratedVersion = get(store, MIGRATION_KEY) || "0.0.0"; let previousMigratedVersion = String(get(store, MIGRATION_KEY)) || "0.0.0";
const newerVersions = Object.entries(migrations) const newerVersions = Object.entries(migrations)
.filter(([candidateVersion]) => _shouldPerformMigration(candidateVersion, previousMigratedVersion, versionToMigrate)); .filter(([candidateVersion]) => _shouldPerformMigration(candidateVersion, previousMigratedVersion, versionToMigrate));
@ -118,7 +119,7 @@ export default getGlobalOverride(getConfigurationFileModelInjectable, (di) => {
} }
catch (error) { catch (error) {
store = storeBackup; store = storeBackup;
throw new Error(`Something went wrong during the migration! Changes applied to the store until this failed migration will be restored. ${error}`); throw new Error(`Something went wrong during the migration! Changes applied to the store until this failed migration will be restored. ${String(error)}`);
} }
} }

View File

@ -8,5 +8,5 @@ import { getRequestChannel } from "@k8slens/messaging";
export const getActiveHelmRepositoriesChannel = getRequestChannel< export const getActiveHelmRepositoriesChannel = getRequestChannel<
void, void,
AsyncResult<HelmRepo[]> AsyncResult<HelmRepo[], string>
>("get-helm-active-list-repositories"); >("get-helm-active-list-repositories");

View File

@ -4,6 +4,7 @@
*/ */
import type { Runnable } from "@k8slens/run-many"; import type { Runnable } from "@k8slens/run-many";
import { isArray } from "@k8slens/utilities";
import type { DiContainerForInjection, Injectable, InjectionToken } from "@ogre-tools/injectable"; import type { DiContainerForInjection, Injectable, InjectionToken } from "@ogre-tools/injectable";
import { getInjectionToken, getInjectable } from "@ogre-tools/injectable"; import { getInjectionToken, getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
@ -67,7 +68,7 @@ export const getInjectablesForInitializable = <T>({
runAfter: rest.runAfter, runAfter: rest.runAfter,
}), }),
injectionToken: (() => { injectionToken: (() => {
if (rest.runAfter && !Array.isArray(rest.runAfter)) { if (rest.runAfter && !isArray(rest.runAfter)) {
return rest.runAfter.injectionToken; return rest.runAfter.injectionToken;
} }

View File

@ -5,7 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { broadcastMessage } from "./ipc"; import { broadcastMessage } from "./ipc";
export type BroadcastMessage = (channel: string, ...args: any[]) => Promise<void>; export type BroadcastMessage = (channel: string, ...args: unknown[]) => Promise<void>;
const broadcastMessageInjectable = getInjectable({ const broadcastMessageInjectable = getInjectable({
id: "broadcast-message", id: "broadcast-message",

View File

@ -10,6 +10,7 @@
import { ipcMain, ipcRenderer, webContents } from "electron"; import { ipcMain, ipcRenderer, webContents } from "electron";
import { toJS } from "../utils/toJS"; import { toJS } from "../utils/toJS";
import type { Disposer } from "@k8slens/utilities"; import type { Disposer } from "@k8slens/utilities";
import { isArray } from "@k8slens/utilities";
import { getLegacyGlobalDiForExtensionApi } from "@k8slens/legacy-global-di"; import { getLegacyGlobalDiForExtensionApi } from "@k8slens/legacy-global-di";
import ipcRendererInjectable from "../../renderer/utils/channel/ipc-renderer.injectable"; import ipcRendererInjectable from "../../renderer/utils/channel/ipc-renderer.injectable";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
@ -18,19 +19,21 @@ import clusterFramesInjectable from "../cluster-frames.injectable";
export const broadcastMainChannel = "ipc:broadcast-main"; export const broadcastMainChannel = "ipc:broadcast-main";
export function ipcMainHandle(channel: string, listener: (event: Electron.IpcMainInvokeEvent, ...args: any[]) => any) { export function ipcMainHandle(channel: string, listener: (event: Electron.IpcMainInvokeEvent, ...args: unknown[]) => unknown) {
const di = getLegacyGlobalDiForExtensionApi(); const di = getLegacyGlobalDiForExtensionApi();
const ipcMain = di.inject(ipcMainInjectionToken); const ipcMain = di.inject(ipcMainInjectionToken);
ipcMain.handle(channel, async (event, ...args) => { ipcMain.handle(channel, async (event, ...args: unknown[]) => {
return sanitizePayload(await listener(event, ...args)); return toJS(await listener(event, ...args));
}); });
} }
export async function broadcastMessage(channel: string, ...args: any[]): Promise<void> { export async function broadcastMessage(channel: string, ...args: unknown[]): Promise<void> {
if (ipcRenderer) { if (ipcRenderer) {
return ipcRenderer.invoke(broadcastMainChannel, channel, ...args.map(sanitizePayload)); await ipcRenderer.invoke(broadcastMainChannel, channel, ...args.map(toJS));
return;
} }
if (!webContents) { if (!webContents) {
@ -41,15 +44,23 @@ export async function broadcastMessage(channel: string, ...args: any[]): Promise
const logger = di.inject(loggerInjectionToken); const logger = di.inject(loggerInjectionToken);
const clusterFrames = di.inject(clusterFramesInjectable); const clusterFrames = di.inject(clusterFramesInjectable);
ipcMain.listeners(channel).forEach((func) => func({ ipcMain.listeners(channel).forEach((func) => {
processId: undefined, frameId: undefined, sender: undefined, senderFrame: undefined, func(
}, ...args)); {
processId: undefined,
frameId: undefined,
sender: undefined,
senderFrame: undefined,
},
...args,
);
});
const views = webContents.getAllWebContents(); const views = webContents.getAllWebContents();
if (!views || !Array.isArray(views) || views.length === 0) return; if (!views || !isArray(views) || views.length === 0) return;
args = args.map(sanitizePayload); args = args.map(toJS);
for (const view of views) { for (const view of views) {
let viewType = "unknown"; let viewType = "unknown";
@ -82,7 +93,7 @@ export async function broadcastMessage(channel: string, ...args: any[]): Promise
} }
} }
export function ipcMainOn(channel: string, listener: (event: Electron.IpcMainEvent, ...args: any[]) => any): Disposer { export function ipcMainOn(channel: string, listener: (event: Electron.IpcMainEvent, ...args: unknown[]) => unknown): Disposer {
const di = getLegacyGlobalDiForExtensionApi(); const di = getLegacyGlobalDiForExtensionApi();
const ipcMain = di.inject(ipcMainInjectionToken); const ipcMain = di.inject(ipcMainInjectionToken);
@ -92,7 +103,7 @@ export function ipcMainOn(channel: string, listener: (event: Electron.IpcMainEve
return () => ipcMain.off(channel, listener); return () => ipcMain.off(channel, listener);
} }
export function ipcRendererOn(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => any): Disposer { export function ipcRendererOn(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: unknown[]) => unknown): Disposer {
const di = getLegacyGlobalDiForExtensionApi(); const di = getLegacyGlobalDiForExtensionApi();
const ipcRenderer = di.inject(ipcRendererInjectable); const ipcRenderer = di.inject(ipcRendererInjectable);
@ -101,11 +112,3 @@ export function ipcRendererOn(channel: string, listener: (event: Electron.IpcRen
return () => ipcRenderer.off(channel, listener); return () => ipcRenderer.off(channel, listener);
} }
/**
* Sanitizing data for IPC-messaging before send.
* Removes possible observable values to avoid exceptions like "can't clone object".
*/
function sanitizePayload<T>(data: any): T {
return toJS(data);
}

View File

@ -57,11 +57,11 @@ export abstract class ItemStore<Item extends ItemObject> {
* @param order whether to sort from least to greatest (`"asc"` (default)) or vice-versa (`"desc"`) * @param order whether to sort from least to greatest (`"asc"` (default)) or vice-versa (`"desc"`)
*/ */
@action @action
protected sortItems(items: Item[] = this.items, sorting: ((item: Item) => any)[] = [this.defaultSorting], order?: "asc" | "desc"): Item[] { protected sortItems(items: Item[] = this.items, sorting: ((item: Item) => unknown)[] = [this.defaultSorting], order?: "asc" | "desc"): Item[] {
return orderBy(items, sorting, order); return orderBy(items, sorting, order);
} }
protected async createItem(...args: any[]): Promise<any>; protected async createItem(...args: unknown[]): Promise<unknown>;
@action @action
protected async createItem(request: () => Promise<Item>) { protected async createItem(request: () => Promise<Item>) {
const newItem = await request(); const newItem = await request();
@ -78,7 +78,7 @@ export abstract class ItemStore<Item extends ItemObject> {
} }
} }
protected async loadItems(...args: any[]): Promise<any>; protected async loadItems(...args: unknown[]): Promise<unknown>;
/** /**
* Load items to this.items * Load items to this.items
* @param request Function to return the items to be loaded. * @param request Function to return the items to be loaded.
@ -87,7 +87,7 @@ export abstract class ItemStore<Item extends ItemObject> {
* @returns * @returns
*/ */
@action @action
protected async loadItems(request: () => Promise<Item[] | any>, sortItems = true, concurrency = false) { protected async loadItems(request: () => Promise<Item[]>, sortItems = true, concurrency = false) {
if (this.isLoading) { if (this.isLoading) {
await when(() => !this.isLoading); await when(() => !this.isLoading);
@ -142,7 +142,7 @@ export abstract class ItemStore<Item extends ItemObject> {
} }
@action @action
protected async removeItem(item: Item, request: () => Promise<any>) { protected async removeItem(item: Item, request: () => Promise<unknown>) {
await request(); await request();
this.items.remove(item); this.items.remove(item);
this.selectedItemsIds.delete(item.getId()); this.selectedItemsIds.delete(item.getId());
@ -173,19 +173,19 @@ export abstract class ItemStore<Item extends ItemObject> {
@action @action
toggleSelectionAll(visibleItems: Item[] = this.items) { toggleSelectionAll(visibleItems: Item[] = this.items) {
const allSelected = visibleItems.every(this.isSelected); const allSelected = visibleItems.every(item => this.isSelected(item));
if (allSelected) { visibleItems.forEach((
visibleItems.forEach(this.unselect); allSelected
} else { ? (item) => this.unselect(item)
visibleItems.forEach(this.select); : (item) => this.select(item)
} ));
} }
isSelectedAll(visibleItems: Item[] = this.items) { isSelectedAll(visibleItems: Item[] = this.items) {
if (!visibleItems.length) return false; if (!visibleItems.length) return false;
return visibleItems.every(this.isSelected); return visibleItems.every((item) => this.isSelected(item));
} }
@action @action
@ -202,7 +202,7 @@ export abstract class ItemStore<Item extends ItemObject> {
this.isLoading = false; this.isLoading = false;
} }
async removeSelectedItems?(): Promise<any>; async removeSelectedItems?(): Promise<unknown>;
async removeItems?(items: Item[]): Promise<void>; async removeItems?(items: Item[]): Promise<void>;

View File

@ -47,7 +47,7 @@ describe("ApiManager", () => {
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs"); di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
di.override(storesAndApisCanBeCreatedInjectable, () => true); di.override(storesAndApisCanBeCreatedInjectable, () => true);
di.override(hostedClusterInjectable, () => new Cluster({ di.override(hostedClusterInjectable, () => Cluster.createForTestingOnly({
contextName: "some-context-name", contextName: "some-context-name",
id: "some-cluster-id", id: "some-cluster-id",
kubeConfigPath: "/some-path-to-a-kubeconfig", kubeConfigPath: "/some-path-to-a-kubeconfig",

View File

@ -12,7 +12,6 @@ import fetchInjectable from "../../fetch/fetch.injectable";
import type { AsyncFnMock } from "@async-fn/jest"; import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn from "@async-fn/jest"; import asyncFn from "@async-fn/jest";
import { flushPromises } from "@k8slens/test-utils"; import { flushPromises } from "@k8slens/test-utils";
import setupAutoRegistrationInjectable from "../../../renderer/before-frame-starts/runnables/setup-auto-registration.injectable";
import { createMockResponseFromString } from "../../../test-utils/mock-responses"; import { createMockResponseFromString } from "../../../test-utils/mock-responses";
import storesAndApisCanBeCreatedInjectable from "../../../renderer/stores-apis-can-be-created.injectable"; 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 directoryForUserDataInjectable from "../../app-paths/directory-for-user-data/directory-for-user-data.injectable";
@ -30,7 +29,7 @@ describe("KubeApi", () => {
let apiManager: ApiManager; let apiManager: ApiManager;
let di: DiContainer; let di: DiContainer;
beforeEach(async () => { beforeEach(() => {
di = getDiForUnitTesting(); di = getDiForUnitTesting();
fetchMock = asyncFn(); fetchMock = asyncFn();
@ -40,17 +39,13 @@ describe("KubeApi", () => {
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs"); di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
di.override(storesAndApisCanBeCreatedInjectable, () => true); di.override(storesAndApisCanBeCreatedInjectable, () => true);
di.override(hostedClusterInjectable, () => new Cluster({ di.override(hostedClusterInjectable, () => Cluster.createForTestingOnly({
contextName: "some-context-name", contextName: "some-context-name",
id: "some-cluster-id", id: "some-cluster-id",
kubeConfigPath: "/some-path-to-a-kubeconfig", kubeConfigPath: "/some-path-to-a-kubeconfig",
})); }));
apiManager = di.inject(apiManagerInjectable); apiManager = di.inject(apiManagerInjectable);
const setupAutoRegistration = di.inject(setupAutoRegistrationInjectable);
setupAutoRegistration.run();
}); });
describe("on first call to IngressApi.get()", () => { describe("on first call to IngressApi.get()", () => {
@ -722,7 +717,7 @@ describe("KubeApi", () => {
], ],
}, },
}); });
horizontalPodAutoscalerApi.get({ void horizontalPodAutoscalerApi.get({
name: "foo", name: "foo",
namespace: "default", namespace: "default",
}); });

View File

@ -14,7 +14,6 @@ import asyncFn from "@async-fn/jest";
import { flushPromises } from "@k8slens/test-utils"; import { flushPromises } from "@k8slens/test-utils";
import createKubeJsonApiInjectable from "../create-kube-json-api.injectable"; import createKubeJsonApiInjectable from "../create-kube-json-api.injectable";
import type { KubeStatusData } from "@k8slens/kube-object"; import type { KubeStatusData } from "@k8slens/kube-object";
import setupAutoRegistrationInjectable from "../../../renderer/before-frame-starts/runnables/setup-auto-registration.injectable";
import { createMockResponseFromString } from "../../../test-utils/mock-responses"; import { createMockResponseFromString } from "../../../test-utils/mock-responses";
import storesAndApisCanBeCreatedInjectable from "../../../renderer/stores-apis-can-be-created.injectable"; 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 directoryForUserDataInjectable from "../../app-paths/directory-for-user-data/directory-for-user-data.injectable";
@ -40,7 +39,7 @@ describe("createKubeApiForRemoteCluster", () => {
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs"); di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
di.override(storesAndApisCanBeCreatedInjectable, () => true); di.override(storesAndApisCanBeCreatedInjectable, () => true);
di.override(hostedClusterInjectable, () => new Cluster({ di.override(hostedClusterInjectable, () => Cluster.createForTestingOnly({
contextName: "some-context-name", contextName: "some-context-name",
id: "some-cluster-id", id: "some-cluster-id",
kubeConfigPath: "/some-path-to-a-kubeconfig", kubeConfigPath: "/some-path-to-a-kubeconfig",
@ -144,7 +143,7 @@ describe("KubeApi", () => {
const createKubeJsonApi = di.inject(createKubeJsonApiInjectable); const createKubeJsonApi = di.inject(createKubeJsonApiInjectable);
di.override(hostedClusterInjectable, () => new Cluster({ di.override(hostedClusterInjectable, () => Cluster.createForTestingOnly({
contextName: "some-context-name", contextName: "some-context-name",
id: "some-cluster-id", id: "some-cluster-id",
kubeConfigPath: "/some-path-to-a-kubeconfig", kubeConfigPath: "/some-path-to-a-kubeconfig",
@ -154,10 +153,6 @@ describe("KubeApi", () => {
serverAddress: `http://127.0.0.1:9999`, serverAddress: `http://127.0.0.1:9999`,
apiBase: "/api-kube", apiBase: "/api-kube",
})); }));
const setupAutoRegistration = di.inject(setupAutoRegistrationInjectable);
setupAutoRegistration.run();
}); });
describe("deleting pods (namespace scoped resource)", () => { describe("deleting pods (namespace scoped resource)", () => {

View File

@ -3,12 +3,12 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { KubeObject } from "@k8slens/kube-object"; import { isJsonApiData, isJsonApiDataList, isPartialJsonApiData } from "@k8slens/kube-object";
describe("KubeObject", () => { describe("KubeObject", () => {
describe("isJsonApiData", () => { describe("isJsonApiData", () => {
{ {
type TestCase = [any]; type TestCase = [unknown];
const tests: TestCase[] = [ const tests: TestCase[] = [
[false], [false],
[true], [true],
@ -22,12 +22,12 @@ describe("KubeObject", () => {
]; ];
it.each(tests)("should reject invalid value: %p", (input) => { it.each(tests)("should reject invalid value: %p", (input) => {
expect(KubeObject.isJsonApiData(input)).toBe(false); expect(isJsonApiData(input)).toBe(false);
}); });
} }
{ {
type TestCase = [string, any]; type TestCase = [string, unknown];
const tests: TestCase[] = [ const tests: TestCase[] = [
["kind", { apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}], ["kind", { apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
["apiVersion", { kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}], ["apiVersion", { kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
@ -38,12 +38,12 @@ describe("KubeObject", () => {
]; ];
it.each(tests)("should reject with missing: %s", (missingField, input) => { it.each(tests)("should reject with missing: %s", (missingField, input) => {
expect(KubeObject.isJsonApiData(input)).toBe(false); expect(isJsonApiData(input)).toBe(false);
}); });
} }
{ {
type TestCase = [string, any]; type TestCase = [string, unknown];
const tests: TestCase[] = [ const tests: TestCase[] = [
["kind", { kind: 1, apiVersion: "", metadata: {}}], ["kind", { kind: 1, apiVersion: "", metadata: {}}],
["apiVersion", { apiVersion: 1, kind: "", metadata: {}}], ["apiVersion", { apiVersion: 1, kind: "", metadata: {}}],
@ -65,20 +65,20 @@ describe("KubeObject", () => {
]; ];
it.each(tests)("should reject with wrong type for field: %s", (missingField, input) => { it.each(tests)("should reject with wrong type for field: %s", (missingField, input) => {
expect(KubeObject.isJsonApiData(input)).toBe(false); expect(isJsonApiData(input)).toBe(false);
}); });
} }
it("should accept valid KubeJsonApiData (ignoring other fields)", () => { it("should accept valid KubeJsonApiData (ignoring other fields)", () => {
const valid = { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: { food: "" }}}; const valid = { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: { food: "" }}};
expect(KubeObject.isJsonApiData(valid)).toBe(true); expect(isJsonApiData(valid)).toBe(true);
}); });
}); });
describe("isPartialJsonApiData", () => { describe("isPartialJsonApiData", () => {
{ {
type TestCase = [any]; type TestCase = [unknown];
const tests: TestCase[] = [ const tests: TestCase[] = [
[false], [false],
[true], [true],
@ -91,16 +91,16 @@ describe("KubeObject", () => {
]; ];
it.each(tests)("should reject invalid value: %p", (input) => { it.each(tests)("should reject invalid value: %p", (input) => {
expect(KubeObject.isPartialJsonApiData(input)).toBe(false); expect(isPartialJsonApiData(input)).toBe(false);
}); });
} }
it("should accept {}", () => { it("should accept {}", () => {
expect(KubeObject.isPartialJsonApiData({})).toBe(true); expect(isPartialJsonApiData({})).toBe(true);
}); });
{ {
type TestCase = [string, any]; type TestCase = [string, unknown];
const tests: TestCase[] = [ const tests: TestCase[] = [
["kind", { apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}], ["kind", { apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
["apiVersion", { kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}], ["apiVersion", { kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
@ -108,12 +108,12 @@ describe("KubeObject", () => {
]; ];
it.each(tests)("should not reject with missing top level field: %s", (missingField, input) => { it.each(tests)("should not reject with missing top level field: %s", (missingField, input) => {
expect(KubeObject.isPartialJsonApiData(input)).toBe(true); expect(isPartialJsonApiData(input)).toBe(true);
}); });
} }
{ {
type TestCase = [string, any]; type TestCase = [string, unknown];
const tests: TestCase[] = [ const tests: TestCase[] = [
["kind", { kind: 1, apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}], ["kind", { kind: 1, apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
["apiVersion", { apiVersion: 1, kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}], ["apiVersion", { apiVersion: 1, kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
@ -135,23 +135,23 @@ describe("KubeObject", () => {
]; ];
it.each(tests)("should reject with wrong type for field: %s", (missingField, input) => { it.each(tests)("should reject with wrong type for field: %s", (missingField, input) => {
expect(KubeObject.isPartialJsonApiData(input)).toBe(false); expect(isPartialJsonApiData(input)).toBe(false);
}); });
} }
it("should accept valid Partial<KubeJsonApiData> (ignoring other fields)", () => { it("should accept valid Partial<KubeJsonApiData> (ignoring other fields)", () => {
const valid = { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: { food: "" }}}; const valid = { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: { food: "" }}};
expect(KubeObject.isPartialJsonApiData(valid)).toBe(true); expect(isPartialJsonApiData(valid)).toBe(true);
}); });
}); });
describe("isJsonApiDataList", () => { describe("isJsonApiDataList", () => {
function isAny(val: unknown): val is any { function isSomething(val: unknown): val is unknown {
return true; return true;
} }
function isNotAny(val: unknown): val is any { function isNotSomething(val: unknown): val is unknown {
return false; return false;
} }
@ -160,7 +160,7 @@ describe("KubeObject", () => {
} }
{ {
type TestCase = [any]; type TestCase = [unknown];
const tests: TestCase[] = [ const tests: TestCase[] = [
[false], [false],
[true], [true],
@ -174,12 +174,12 @@ describe("KubeObject", () => {
]; ];
it.each(tests)("should reject invalid value: %p", (input) => { it.each(tests)("should reject invalid value: %p", (input) => {
expect(KubeObject.isJsonApiDataList(input, isAny)).toBe(false); expect(isJsonApiDataList(input, isSomething)).toBe(false);
}); });
} }
{ {
type TestCase = [string, any]; type TestCase = [string, unknown];
const tests: TestCase[] = [ const tests: TestCase[] = [
["kind", { apiVersion: "", items: [], metadata: { resourceVersion: "", selfLink: "" }}], ["kind", { apiVersion: "", items: [], metadata: { resourceVersion: "", selfLink: "" }}],
["apiVersion", { kind: "", items: [], metadata: { resourceVersion: "", selfLink: "" }}], ["apiVersion", { kind: "", items: [], metadata: { resourceVersion: "", selfLink: "" }}],
@ -187,12 +187,12 @@ describe("KubeObject", () => {
]; ];
it.each(tests)("should reject with missing: %s", (missingField, input) => { it.each(tests)("should reject with missing: %s", (missingField, input) => {
expect(KubeObject.isJsonApiDataList(input, isAny)).toBe(false); expect(isJsonApiDataList(input, isSomething)).toBe(false);
}); });
} }
{ {
type TestCase = [string, any]; type TestCase = [string, unknown];
const tests: TestCase[] = [ const tests: TestCase[] = [
["kind", { kind: 1, items: [], apiVersion: "", metadata: { resourceVersion: "", selfLink: "" }}], ["kind", { kind: 1, items: [], apiVersion: "", metadata: { resourceVersion: "", selfLink: "" }}],
["apiVersion", { kind: "", items: [], apiVersion: 1, metadata: { resourceVersion: "", selfLink: "" }}], ["apiVersion", { kind: "", items: [], apiVersion: 1, metadata: { resourceVersion: "", selfLink: "" }}],
@ -206,14 +206,14 @@ describe("KubeObject", () => {
]; ];
it.each(tests)("should reject with wrong type for field: %s", (missingField, input) => { it.each(tests)("should reject with wrong type for field: %s", (missingField, input) => {
expect(KubeObject.isJsonApiDataList(input, isNotAny)).toBe(false); expect(isJsonApiDataList(input, isNotSomething)).toBe(false);
}); });
} }
it("should accept valid KubeJsonApiDataList (ignoring other fields)", () => { it("should accept valid KubeJsonApiDataList (ignoring other fields)", () => {
const valid = { kind: "", items: [false], apiVersion: "", metadata: { resourceVersion: "", selfLink: "" }}; const valid = { kind: "", items: [false], apiVersion: "", metadata: { resourceVersion: "", selfLink: "" }};
expect(KubeObject.isJsonApiDataList(valid, isBoolean)).toBe(true); expect(isJsonApiDataList(valid, isBoolean)).toBe(true);
}); });
}); });
}); });

View File

@ -13,10 +13,10 @@ import { parseKubeApi, createKubeApiURL } from "@k8slens/kube-api";
import { getOrInsertWith, iter } from "@k8slens/utilities"; import { getOrInsertWith, iter } from "@k8slens/utilities";
import type { CreateCustomResourceStore } from "./create-custom-resource-store.injectable"; import type { CreateCustomResourceStore } from "./create-custom-resource-store.injectable";
export type RegisterableStore<Store> = Store extends KubeObjectStore<any, any, any> export type RegisterableStore<Store> = Store extends KubeObjectStore
? Store ? Store
: never; : never;
export type RegisterableApi<Api> = Api extends KubeApi<any, any> export type RegisterableApi<Api> = Api extends KubeApi
? Api ? Api
: never; : never;
export type KubeObjectStoreFrom<Api> = Api extends KubeApi<infer KubeObj, infer ApiData> export type KubeObjectStoreFrom<Api> = Api extends KubeApi<infer KubeObj, infer ApiData>

View File

@ -1,25 +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 EventEmitter from "events";
import type TypedEventEmitter from "typed-emitter";
import type { KubeApi } from "@k8slens/kube-api";
export interface LegacyAutoRegistration {
kubeApi: (api: KubeApi<any, any>) => void;
}
/**
* This is used to remove dependency cycles from auto registering of instances
*
* - Custom Resource Definitions get their own registered store (will need in the future)
* - All KubeApi's get auto registered (this should be changed in the future)
*/
const autoRegistrationEmitterInjectable = getInjectable({
id: "auto-registration-emitter",
instantiate: (): TypedEventEmitter<LegacyAutoRegistration> => new EventEmitter(),
});
export default autoRegistrationEmitterInjectable;

View File

@ -2,9 +2,24 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectionToken } from "@ogre-tools/injectable"; import type { DiContainerForInjection } from "@ogre-tools/injectable";
import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
import type { KubeObjectStore } from "../kube-object.store"; import type { KubeObjectStore } from "../kube-object.store";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const kubeObjectStoreInjectionToken = getInjectionToken<KubeObjectStore<any, any, any>>({ export const kubeObjectStoreInjectionToken = getInjectionToken<KubeObjectStore<any, any, any>>({
id: "kube-object-store-token", id: "kube-object-store-token",
}); });
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export interface KubeStoreInjectableParts<Store extends KubeObjectStore<any, any, any>> {
id: string;
instantiate: (di: DiContainerForInjection) => Store;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const getKubeStoreInjectable = <Store extends KubeObjectStore<any, any, any>>(parts: KubeStoreInjectableParts<Store>) => getInjectable({
id: parts.id,
instantiate: (di) => parts.instantiate(di),
injectionToken: kubeObjectStoreInjectionToken,
});

View File

@ -24,11 +24,11 @@ const createJsonApiInjectable = getInjectable({
return (config, reqInit) => { return (config, reqInit) => {
if (!config.getRequestOptions) { if (!config.getRequestOptions) {
config.getRequestOptions = async () => { config.getRequestOptions = () => {
const agent = new Agent({ const agent = new Agent({
ca: lensProxyCert.get().cert, ca: lensProxyCert.get().cert,
}); });
return { return {
agent, agent,
}; };

View File

@ -19,16 +19,16 @@ export interface CreateKubeApiForLocalClusterConfig {
} }
export interface CreateKubeApiForCluster { export interface CreateKubeApiForCluster {
<Object extends KubeObject, Api extends KubeApi<Object>, Data extends KubeJsonApiDataFor<Object>>( <Kube extends KubeObject, Api extends KubeApi<Kube>, Data extends KubeJsonApiDataFor<Kube>>(
cluster: CreateKubeApiForLocalClusterConfig, cluster: CreateKubeApiForLocalClusterConfig,
kubeClass: KubeObjectConstructor<Object, Data>, kubeClass: KubeObjectConstructor<Kube, Data>,
apiClass: KubeApiConstructor<Object, Api>, apiClass: KubeApiConstructor<Kube, Api>,
): Api; ): Api;
<Object extends KubeObject, Data extends KubeJsonApiDataFor<Object>>( <Kube extends KubeObject, Data extends KubeJsonApiDataFor<Kube>>(
cluster: CreateKubeApiForLocalClusterConfig, cluster: CreateKubeApiForLocalClusterConfig,
kubeClass: KubeObjectConstructor<Object, Data>, kubeClass: KubeObjectConstructor<Kube, Data>,
apiClass?: KubeApiConstructor<Object, KubeApi<Object>>, apiClass?: KubeApiConstructor<Kube, KubeApi<Kube>>,
): KubeApi<Object>; ): KubeApi<Kube>;
} }
const createKubeApiForClusterInjectable = getInjectable({ const createKubeApiForClusterInjectable = getInjectable({

View File

@ -33,19 +33,19 @@ export interface CreateKubeApiForRemoteClusterConfig {
agent?: Agent; agent?: Agent;
} }
export type KubeApiConstructor<Object extends KubeObject, Api extends KubeApi<Object>> = new (apiOpts: KubeApiOptions<Object>) => Api; export type KubeApiConstructor<Kube extends KubeObject, Api extends KubeApi<Kube>> = new (apiOpts: KubeApiOptions<Kube>) => Api;
export interface CreateKubeApiForRemoteCluster { export interface CreateKubeApiForRemoteCluster {
<Object extends KubeObject, Api extends KubeApi<Object>, Data extends KubeJsonApiDataFor<Object>>( <Kube extends KubeObject, Api extends KubeApi<Kube>, Data extends KubeJsonApiDataFor<Kube>>(
config: CreateKubeApiForRemoteClusterConfig, config: CreateKubeApiForRemoteClusterConfig,
kubeClass: KubeObjectConstructor<Object, Data>, kubeClass: KubeObjectConstructor<Kube, Data>,
apiClass: KubeApiConstructor<Object, Api>, apiClass: KubeApiConstructor<Kube, Api>,
): Api; ): Api;
<Object extends KubeObject, Data extends KubeJsonApiDataFor<Object>>( <Kube extends KubeObject, Data extends KubeJsonApiDataFor<Kube>>(
config: CreateKubeApiForRemoteClusterConfig, config: CreateKubeApiForRemoteClusterConfig,
kubeClass: KubeObjectConstructor<Object, Data>, kubeClass: KubeObjectConstructor<Kube, Data>,
apiClass?: KubeApiConstructor<Object, KubeApi<Object>>, apiClass?: KubeApiConstructor<Kube, KubeApi<Kube>>,
): KubeApi<Object>; ): KubeApi<Kube>;
} }
const createKubeApiForRemoteClusterInjectable = getInjectable({ const createKubeApiForRemoteClusterInjectable = getInjectable({

View File

@ -24,17 +24,17 @@ const createKubeJsonApiInjectable = getInjectable({
return (config, reqInit) => { return (config, reqInit) => {
if (!config.getRequestOptions) { if (!config.getRequestOptions) {
config.getRequestOptions = async () => { config.getRequestOptions = () => {
const agent = new Agent({ const agent = new Agent({
ca: lensProxyCert.get().cert, ca: lensProxyCert.get().cert,
}); });
return { return {
agent, agent,
}; };
}; };
} }
return new KubeJsonApi(dependencies, config, reqInit); return new KubeJsonApi(dependencies, config, reqInit);
}; };
}, },

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { ClusterRoleBindingApi } from "@k8slens/kube-api"; import { ClusterRoleBindingApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const clusterRoleBindingApiInjectable = getInjectable({ const clusterRoleBindingApiInjectable = getKubeApiInjectable({
id: "cluster-role-binding-api", id: "cluster-role-binding-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "clusterRoleBindingApi is only accessible in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "clusterRoleBindingApi is only accessible in certain environments");
@ -20,8 +19,6 @@ const clusterRoleBindingApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default clusterRoleBindingApiInjectable; export default clusterRoleBindingApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { ClusterRoleApi } from "@k8slens/kube-api"; import { ClusterRoleApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const clusterRoleApiInjectable = getInjectable({ const clusterRoleApiInjectable = getKubeApiInjectable({
id: "cluster-role-api", id: "cluster-role-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "clusterRoleApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "clusterRoleApi is only available in certain environments");
@ -20,8 +19,6 @@ const clusterRoleApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default clusterRoleApiInjectable; export default clusterRoleApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { ClusterApi } from "@k8slens/kube-api"; import { ClusterApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const clusterApiInjectable = getInjectable({ const clusterApiInjectable = getKubeApiInjectable({
id: "cluster-api", id: "cluster-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "clusterApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "clusterApi is only available in certain environments");
@ -20,8 +19,6 @@ const clusterApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default clusterApiInjectable; export default clusterApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { ComponentStatusApi } from "@k8slens/kube-api"; import { ComponentStatusApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
const componentStatusApiInjectable = getInjectable({ const componentStatusApiInjectable = getKubeApiInjectable({
id: "component-status-api", id: "component-status-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "componentStatusApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "componentStatusApi is only available in certain environments");
@ -20,8 +19,6 @@ const componentStatusApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default componentStatusApiInjectable; export default componentStatusApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { ConfigMapApi } from "@k8slens/kube-api"; import { ConfigMapApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const configMapApiInjectable = getInjectable({ const configMapApiInjectable = getKubeApiInjectable({
id: "config-map-api", id: "config-map-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "configMapApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "configMapApi is only available in certain environments");
@ -20,8 +19,6 @@ const configMapApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default configMapApiInjectable; export default configMapApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { CronJobApi } from "@k8slens/kube-api"; import { CronJobApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const cronJobApiInjectable = getInjectable({ const cronJobApiInjectable = getKubeApiInjectable({
id: "cron-job-api", id: "cron-job-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "cronJobApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "cronJobApi is only available in certain environments");
@ -22,8 +21,6 @@ const cronJobApiInjectable = getInjectable({
checkPreferredVersion: true, checkPreferredVersion: true,
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default cronJobApiInjectable; export default cronJobApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { CustomResourceDefinitionApi } from "@k8slens/kube-api"; import { CustomResourceDefinitionApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
const customResourceDefinitionApiInjectable = getInjectable({ const customResourceDefinitionApiInjectable = getKubeApiInjectable({
id: "custom-resource-definition-api", id: "custom-resource-definition-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "customResourceDefinitionApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "customResourceDefinitionApi is only available in certain environments");
@ -20,8 +19,6 @@ const customResourceDefinitionApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default customResourceDefinitionApiInjectable; export default customResourceDefinitionApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { DaemonSetApi } from "@k8slens/kube-api"; import { DaemonSetApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const daemonSetApiInjectable = getInjectable({ const daemonSetApiInjectable = getKubeApiInjectable({
id: "daemon-set-api", id: "daemon-set-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "daemonSetApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "daemonSetApi is only available in certain environments");
@ -20,8 +19,6 @@ const daemonSetApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default daemonSetApiInjectable; export default daemonSetApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { DeploymentApi } from "@k8slens/kube-api"; import { DeploymentApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const deploymentApiInjectable = getInjectable({ const deploymentApiInjectable = getKubeApiInjectable({
id: "deployment-api", id: "deployment-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "deploymentApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "deploymentApi is only available in certain environments");
@ -20,8 +19,6 @@ const deploymentApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default deploymentApiInjectable; export default deploymentApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { EndpointsApi } from "@k8slens/kube-api"; import { EndpointsApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const endpointsApiInjectable = getInjectable({ const endpointsApiInjectable = getKubeApiInjectable({
id: "endpoints-api", id: "endpoints-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "endpointsApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "endpointsApi is only available in certain environments");
@ -20,8 +19,6 @@ const endpointsApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default endpointsApiInjectable; export default endpointsApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { KubeEventApi } from "@k8slens/kube-api"; import { KubeEventApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const kubeEventApiInjectable = getInjectable({ const kubeEventApiInjectable = getKubeApiInjectable({
id: "kube-event-api", id: "kube-event-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "kubeEventApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "kubeEventApi is only available in certain environments");
@ -20,8 +19,6 @@ const kubeEventApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default kubeEventApiInjectable; export default kubeEventApiInjectable;

View File

@ -3,9 +3,8 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { array } from "@k8slens/utilities";
import autoBind from "auto-bind"; import autoBind from "auto-bind";
import Joi from "joi"; import { z } from "zod";
export interface RawHelmChart { export interface RawHelmChart {
apiVersion: string; apiVersion: string;
@ -31,132 +30,51 @@ export interface RawHelmChart {
annotations?: Record<string, string>; annotations?: Record<string, string>;
} }
const helmChartMaintainerValidator = Joi.object<HelmChartMaintainer>({ const helmChartMaintainerSchema = z.object({
name: Joi name: z.string(),
.string() email: z.string(),
.required(), url: z.string().optional(),
email: Joi
.string()
.required(),
url: Joi
.string()
.optional(),
}); });
const helmChartDependencyValidator = Joi.object<HelmChartDependency, true, RawHelmChartDependency>({ const helmChartDependencySchema = z.object({
name: Joi name: z.string(),
.string() repository: z.string(),
.required(), condition: z.string().optional(),
repository: Joi version: z.string(),
.string() tags: z.array(z.string()).default(() => []),
.required(),
condition: Joi
.string()
.optional(),
version: Joi
.string()
.required(),
tags: Joi
.array()
.items(Joi.string())
.default(() => ([])),
}); });
const helmChartValidator = Joi.object<HelmChart, true, RawHelmChart>({ const helmChartValidator = z.object({
apiVersion: Joi apiVersion: z.string(),
.string() name: z.string(),
.required(), version: z.string(),
name: Joi repo: z.string(),
.string() created: z.string(),
.required(), digest: z.string().optional(),
version: Joi kubeVersion: z.string()
.string()
.required(),
repo: Joi
.string()
.required(),
created: Joi
.string()
.required(),
digest: Joi
.string()
.optional(), .optional(),
kubeVersion: Joi description: z.string()
.string()
.optional(),
description: Joi
.string()
.default(""), .default(""),
home: Joi home: z.string()
.string()
.optional(), .optional(),
engine: Joi engine: z.string()
.string()
.optional(), .optional(),
icon: Joi icon: z.string()
.string()
.optional(), .optional(),
appVersion: Joi appVersion: z.string()
.string()
.optional(), .optional(),
tillerVersion: Joi tillerVersion: z.string()
.string()
.optional(), .optional(),
type: Joi type: z.string()
.string()
.optional(), .optional(),
deprecated: Joi deprecated: z.boolean()
.boolean()
.default(false), .default(false),
keywords: Joi keywords: z.array(z.string()).default(() => ([])),
.array() sources: z.array(z.string()).default(() => ([])),
.items(Joi.string()) urls: z.array(z.string()).default(() => ([])),
.options({ maintainers: z.array(helmChartMaintainerSchema).default(() => ([])),
stripUnknown: { dependencies: z.array(helmChartDependencySchema).default(() => ([])),
arrays: true, annotations: z.record(z.string()).default(() => ({})),
},
})
.default(() => ([])),
sources: Joi
.array()
.items(Joi.string())
.options({
stripUnknown: {
arrays: true,
},
})
.default(() => ([])),
urls: Joi
.array()
.items(Joi.string())
.options({
stripUnknown: {
arrays: true,
},
})
.default(() => ([])),
maintainers: Joi
.array()
.items(helmChartMaintainerValidator)
.options({
stripUnknown: {
arrays: true,
},
})
.default(() => ([])),
dependencies: Joi
.array()
.items(helmChartDependencyValidator)
.options({
stripUnknown: {
arrays: true,
},
})
.default(() => ([])),
annotations: Joi
.object({})
.pattern(/.*/, Joi.string())
.default(() => ({})),
}); });
export interface HelmChartCreateOpts { export interface HelmChartCreateOpts {
@ -256,31 +174,17 @@ export class HelmChart implements HelmChartData {
static create(data: RawHelmChart): HelmChart; static create(data: RawHelmChart): HelmChart;
static create(data: RawHelmChart, opts?: HelmChartCreateOpts): HelmChart | undefined; static create(data: RawHelmChart, opts?: HelmChartCreateOpts): HelmChart | undefined;
static create(data: RawHelmChart, { onError = "throw" }: HelmChartCreateOpts = {}): HelmChart | undefined { static create(data: RawHelmChart, { onError = "throw" }: HelmChartCreateOpts = {}): HelmChart | undefined {
const result = helmChartValidator.validate(data, { const result = helmChartValidator.safeParse(data);
abortEarly: false,
});
if (!result.error) { if (result.success) {
return new HelmChart(result.value); return new HelmChart(result.data);
} }
const [actualErrors, unknownDetails] = array.bifurcate(result.error.details, ({ type }) => type === "object.unknown");
if (unknownDetails.length > 0) {
console.warn("HelmChart data has unexpected fields", { original: data, unknownFields: unknownDetails.flatMap(d => d.path) });
}
if (actualErrors.length === 0) {
return new HelmChart(result.value as unknown as HelmChartData);
}
const validationError = new Joi.ValidationError(actualErrors.map(er => er.message).join(". "), actualErrors, result.error._original);
if (onError === "throw") { if (onError === "throw") {
throw validationError; throw result.error;
} }
console.warn("[HELM-CHART]: failed to validate data", data, validationError); console.warn("[HELM-CHART]: failed to validate data", data, result.error);
return undefined; return undefined;
} }
@ -289,16 +193,20 @@ export class HelmChart implements HelmChartData {
const digestPart = this.digest const digestPart = this.digest
? `+${this.digest}` ? `+${this.digest}`
: ""; : "";
const version = this.getAppVersion();
const versionId = version
? `@${version}`
: "";
return `${this.repo}:${this.apiVersion}/${this.name}@${this.getAppVersion()}${digestPart}`; return `${this.repo}:${this.apiVersion}/${this.name}${versionId}${digestPart}`;
} }
getName(): string { getName(): string {
return this.name; return this.name;
} }
getFullName(seperator = "/"): string { getFullName(separator = "/"): string {
return [this.getRepository(), this.getName()].join(seperator); return [this.getRepository(), this.getName()].join(separator);
} }
getDescription(): string { getDescription(): string {

View File

@ -9,7 +9,7 @@ import apiBaseInjectable from "../../api-base.injectable";
const requestReadmeEndpoint = urlBuilderFor("/v2/charts/:repo/:name/readme"); const requestReadmeEndpoint = urlBuilderFor("/v2/charts/:repo/:name/readme");
export type RequestHelmChartReadme = (repo: string, name: string, version?: string) => AsyncResult<string>; export type RequestHelmChartReadme = (repo: string, name: string, version?: string) => AsyncResult<string, string>;
const requestHelmChartReadmeInjectable = getInjectable({ const requestHelmChartReadmeInjectable = getInjectable({
id: "request-helm-chart-readme", id: "request-helm-chart-readme",

View File

@ -9,7 +9,7 @@ import apiBaseInjectable from "../../api-base.injectable";
const requestValuesEndpoint = urlBuilderFor("/v2/charts/:repo/:name/values"); const requestValuesEndpoint = urlBuilderFor("/v2/charts/:repo/:name/values");
export type RequestHelmChartValues = (repo: string, name: string, version: string) => AsyncResult<string>; export type RequestHelmChartValues = (repo: string, name: string, version: string) => AsyncResult<string, string>;
const requestHelmChartValuesInjectable = getInjectable({ const requestHelmChartValuesInjectable = getInjectable({
id: "request-helm-chart-values", id: "request-helm-chart-values",

View File

@ -38,10 +38,10 @@ const requestHelmReleaseUpdateInjectable = getInjectable({
}, },
}); });
} catch (e) { } catch (e) {
return { callWasSuccessful: false, error: e }; return { isOk: false, error: e };
} }
return { callWasSuccessful: true }; return { isOk: true };
}; };
}, },
}); });

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { HorizontalPodAutoscalerApi } from "@k8slens/kube-api"; import { HorizontalPodAutoscalerApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const horizontalPodAutoscalerApiInjectable = getInjectable({ const horizontalPodAutoscalerApiInjectable = getKubeApiInjectable({
id: "horizontal-pod-autoscaler-api", id: "horizontal-pod-autoscaler-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "horizontalPodAutoscalerApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "horizontalPodAutoscalerApi is only available in certain environments");
@ -20,8 +19,6 @@ const horizontalPodAutoscalerApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default horizontalPodAutoscalerApiInjectable; export default horizontalPodAutoscalerApiInjectable;

View File

@ -2,20 +2,23 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import { IngressClassApi } from "@k8slens/kube-api"; import { IngressClassApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import assert from "assert";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
const ingressClassApiInjectable = getInjectable({ const ingressClassApiInjectable = getKubeApiInjectable({
id: "ingress-class-api", id: "ingress-class-api",
instantiate: (di) => new IngressClassApi({ instantiate: (di) => {
logger: di.inject(loggerInjectionToken), assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "ingressClassApi is only available in certain environments");
maybeKubeApi: di.inject(maybeKubeApiInjectable),
}),
injectionToken: kubeApiInjectionToken, return new IngressClassApi({
logger: di.inject(loggerInjectionToken),
maybeKubeApi: di.inject(maybeKubeApiInjectable),
});
},
}); });
export default ingressClassApiInjectable; export default ingressClassApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { IngressApi } from "@k8slens/kube-api"; import { IngressApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const ingressApiInjectable = getInjectable({ const ingressApiInjectable = getKubeApiInjectable({
id: "ingress-api", id: "ingress-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "ingressApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "ingressApi is only available in certain environments");
@ -20,8 +19,6 @@ const ingressApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default ingressApiInjectable; export default ingressApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { JobApi } from "@k8slens/kube-api"; import { JobApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const jobApiInjectable = getInjectable({ const jobApiInjectable = getKubeApiInjectable({
id: "job-api", id: "job-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "jobApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "jobApi is only available in certain environments");
@ -22,8 +21,6 @@ const jobApiInjectable = getInjectable({
checkPreferredVersion: true, checkPreferredVersion: true,
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default jobApiInjectable; export default jobApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { LeaseApi } from "@k8slens/kube-api"; import { LeaseApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const leaseApiInjectable = getInjectable({ const leaseApiInjectable = getKubeApiInjectable({
id: "lease-api", id: "lease-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "leaseApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "leaseApi is only available in certain environments");
@ -20,8 +19,6 @@ const leaseApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default leaseApiInjectable; export default leaseApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { LimitRangeApi } from "@k8slens/kube-api"; import { LimitRangeApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const limitRangeApiInjectable = getInjectable({ const limitRangeApiInjectable = getKubeApiInjectable({
id: "limit-range-api", id: "limit-range-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "limitRangeApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "limitRangeApi is only available in certain environments");
@ -20,8 +19,6 @@ const limitRangeApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default limitRangeApiInjectable; export default limitRangeApiInjectable;

View File

@ -2,26 +2,23 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { MutatingWebhookConfigurationApi } from "@k8slens/kube-api"; import { MutatingWebhookConfigurationApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const mutatingWebhookConfigurationApiInjectable = getInjectable({ const mutatingWebhookConfigurationApiInjectable = getKubeApiInjectable({
id: "mutating-webhook-configuration", id: "mutating-webhook-configuration",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "mutatingWebhookApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "mutatingWebhookConfigurationApi is only available in certain environments");
return new MutatingWebhookConfigurationApi({ return new MutatingWebhookConfigurationApi({
logger: di.inject(loggerInjectionToken), logger: di.inject(loggerInjectionToken),
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default mutatingWebhookConfigurationApiInjectable; export default mutatingWebhookConfigurationApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { NamespaceApi } from "@k8slens/kube-api"; import { NamespaceApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const namespaceApiInjectable = getInjectable({ const namespaceApiInjectable = getKubeApiInjectable({
id: "namespace-api", id: "namespace-api",
instantiate: (di) => { instantiate: (di) => {
@ -21,8 +20,6 @@ const namespaceApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default namespaceApiInjectable; export default namespaceApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { NetworkPolicyApi } from "@k8slens/kube-api"; import { NetworkPolicyApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const networkPolicyApiInjectable = getInjectable({ const networkPolicyApiInjectable = getKubeApiInjectable({
id: "network-policy-api", id: "network-policy-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "networkPolicyApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "networkPolicyApi is only available in certain environments");
@ -20,8 +19,6 @@ const networkPolicyApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default networkPolicyApiInjectable; export default networkPolicyApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { NodeApi } from "@k8slens/kube-api"; import { NodeApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const nodeApiInjectable = getInjectable({ const nodeApiInjectable = getKubeApiInjectable({
id: "node-api", id: "node-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "nodeApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "nodeApi is only available in certain environments");
@ -20,8 +19,6 @@ const nodeApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default nodeApiInjectable; export default nodeApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { PersistentVolumeClaimApi } from "@k8slens/kube-api"; import { PersistentVolumeClaimApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const persistentVolumeClaimApiInjectable = getInjectable({ const persistentVolumeClaimApiInjectable = getKubeApiInjectable({
id: "persistent-volume-claim-api", id: "persistent-volume-claim-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "persistentVolumeClaimApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "persistentVolumeClaimApi is only available in certain environments");
@ -20,8 +19,6 @@ const persistentVolumeClaimApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default persistentVolumeClaimApiInjectable; export default persistentVolumeClaimApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { PersistentVolumeApi } from "@k8slens/kube-api"; import { PersistentVolumeApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const persistentVolumeApiInjectable = getInjectable({ const persistentVolumeApiInjectable = getKubeApiInjectable({
id: "persistent-volume-api", id: "persistent-volume-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "persistentVolumeApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "persistentVolumeApi is only available in certain environments");
@ -20,8 +19,6 @@ const persistentVolumeApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default persistentVolumeApiInjectable; export default persistentVolumeApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { PodDisruptionBudgetApi } from "@k8slens/kube-api"; import { PodDisruptionBudgetApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const podDisruptionBudgetApiInjectable = getInjectable({ const podDisruptionBudgetApiInjectable = getKubeApiInjectable({
id: "pod-disruption-budget-api", id: "pod-disruption-budget-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "podDisruptionBudgetApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "podDisruptionBudgetApi is only available in certain environments");
@ -28,8 +27,6 @@ const podDisruptionBudgetApiInjectable = getInjectable({
}, },
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default podDisruptionBudgetApiInjectable; export default podDisruptionBudgetApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { PodMetricsApi } from "@k8slens/kube-api"; import { PodMetricsApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const podMetricsApiInjectable = getInjectable({ const podMetricsApiInjectable = getKubeApiInjectable({
id: "pod-metrics-api", id: "pod-metrics-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "podMetricsApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "podMetricsApi is only available in certain environments");
@ -20,8 +19,6 @@ const podMetricsApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default podMetricsApiInjectable; export default podMetricsApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { PodSecurityPolicyApi } from "@k8slens/kube-api"; import { PodSecurityPolicyApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const podSecurityPolicyApiInjectable = getInjectable({ const podSecurityPolicyApiInjectable = getKubeApiInjectable({
id: "pod-security-policy-api", id: "pod-security-policy-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "podSecurityPolicyApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "podSecurityPolicyApi is only available in certain environments");
@ -20,8 +19,6 @@ const podSecurityPolicyApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default podSecurityPolicyApiInjectable; export default podSecurityPolicyApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { PodApi } from "@k8slens/kube-api"; import { PodApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const podApiInjectable = getInjectable({ const podApiInjectable = getKubeApiInjectable({
id: "pod-api", id: "pod-api",
instantiate: (di) => { instantiate: (di) => {
@ -21,8 +20,6 @@ const podApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default podApiInjectable; export default podApiInjectable;

View File

@ -2,26 +2,23 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { PriorityClassApi } from "@k8slens/kube-api"; import { PriorityClassApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const priorityClassApiInjectable = getInjectable({ const priorityClassApiInjectable = getKubeApiInjectable({
id: "priority-class-api", id: "priority-class-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "PriorityClassApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "priorityClassApi is only available in certain environments");
return new PriorityClassApi({ return new PriorityClassApi({
logger: di.inject(loggerInjectionToken), logger: di.inject(loggerInjectionToken),
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default priorityClassApiInjectable; export default priorityClassApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { ReplicaSetApi } from "@k8slens/kube-api"; import { ReplicaSetApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const replicaSetApiInjectable = getInjectable({ const replicaSetApiInjectable = getKubeApiInjectable({
id: "replica-set-api", id: "replica-set-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "replicaSetApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "replicaSetApi is only available in certain environments");
@ -20,8 +19,6 @@ const replicaSetApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default replicaSetApiInjectable; export default replicaSetApiInjectable;

View File

@ -2,22 +2,23 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import { ReplicationControllerApi } from "@k8slens/kube-api"; import { ReplicationControllerApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import assert from "assert";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
const replicationControllerApiInjectable = getInjectable({ const replicationControllerApiInjectable = getKubeApiInjectable({
id: "replication-controller-api", id: "replication-controller-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "replicationControllerApi is only available in certain environments");
return new ReplicationControllerApi({ return new ReplicationControllerApi({
logger: di.inject(loggerInjectionToken), logger: di.inject(loggerInjectionToken),
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default replicationControllerApiInjectable; export default replicationControllerApiInjectable;

View File

@ -25,20 +25,20 @@ const requestKubeObjectPatchInjectable = getInjectable({
}, },
})) as Result<string, string>; })) as Result<string, string>;
if (!result.callWasSuccessful) { if (!result.isOk) {
return result; return result;
} }
try { try {
const response = JSON.parse(result.response) as KubeJsonApiData; const response = JSON.parse(result.value) as KubeJsonApiData;
return { return {
callWasSuccessful: true, isOk: true,
response, response,
}; };
} catch (error) { } catch (error) {
return { return {
callWasSuccessful: false, isOk: false,
error: String(error), error: String(error),
}; };
} }

View File

@ -17,20 +17,20 @@ const requestKubeObjectCreationInjectable = getInjectable({
return async (data) => { return async (data) => {
const result = await apiBase.post("/stack", { data }) as Result<string, string>; const result = await apiBase.post("/stack", { data }) as Result<string, string>;
if (!result.callWasSuccessful) { if (!result.isOk) {
return result; return result;
} }
try { try {
const response = JSON.parse(result.response); const response = JSON.parse(result.value) as KubeJsonApiData;
return { return {
callWasSuccessful: true, isOk: true,
response, response,
}; };
} catch (error) { } catch (error) {
return { return {
callWasSuccessful: false, isOk: false,
error: String(error), error: String(error),
}; };
} }

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { ResourceQuotaApi } from "@k8slens/kube-api"; import { ResourceQuotaApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const resourceQuotaApiInjectable = getInjectable({ const resourceQuotaApiInjectable = getKubeApiInjectable({
id: "resource-quota-api", id: "resource-quota-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "resourceQuotaApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "resourceQuotaApi is only available in certain environments");
@ -20,8 +19,6 @@ const resourceQuotaApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default resourceQuotaApiInjectable; export default resourceQuotaApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { RoleBindingApi } from "@k8slens/kube-api"; import { RoleBindingApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const roleBindingApiInjectable = getInjectable({ const roleBindingApiInjectable = getKubeApiInjectable({
id: "role-binding-api", id: "role-binding-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "roleBindingApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "roleBindingApi is only available in certain environments");
@ -20,8 +19,6 @@ const roleBindingApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default roleBindingApiInjectable; export default roleBindingApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { RoleApi } from "@k8slens/kube-api"; import { RoleApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const roleApiInjectable = getInjectable({ const roleApiInjectable = getKubeApiInjectable({
id: "role-api", id: "role-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "roleApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "roleApi is only available in certain environments");
@ -20,8 +19,6 @@ const roleApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default roleApiInjectable; export default roleApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { RuntimeClassApi } from "@k8slens/kube-api"; import { RuntimeClassApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const runtimeClassApiInjectable = getInjectable({ const runtimeClassApiInjectable = getKubeApiInjectable({
id: "runtime-class-api", id: "runtime-class-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "RuntimeClassApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "RuntimeClassApi is only available in certain environments");
@ -20,8 +19,6 @@ const runtimeClassApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default runtimeClassApiInjectable; export default runtimeClassApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { SecretApi } from "@k8slens/kube-api"; import { SecretApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const secretApiInjectable = getInjectable({ const secretApiInjectable = getKubeApiInjectable({
id: "secret-api", id: "secret-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "secretApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "secretApi is only available in certain environments");
@ -20,8 +19,6 @@ const secretApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default secretApiInjectable; export default secretApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { SelfSubjectRulesReviewApi } from "@k8slens/kube-api"; import { SelfSubjectRulesReviewApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const selfSubjectRulesReviewApiInjectable = getInjectable({ const selfSubjectRulesReviewApiInjectable = getKubeApiInjectable({
id: "self-subject-rules-review-api", id: "self-subject-rules-review-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "selfSubjectRulesReviewApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "selfSubjectRulesReviewApi is only available in certain environments");
@ -20,8 +19,6 @@ const selfSubjectRulesReviewApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default selfSubjectRulesReviewApiInjectable; export default selfSubjectRulesReviewApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { ServiceAccountApi } from "@k8slens/kube-api"; import { ServiceAccountApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const serviceAccountApiInjectable = getInjectable({ const serviceAccountApiInjectable = getKubeApiInjectable({
id: "service-account-api", id: "service-account-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "serviceAccountApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "serviceAccountApi is only available in certain environments");
@ -20,8 +19,6 @@ const serviceAccountApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default serviceAccountApiInjectable; export default serviceAccountApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { ServiceApi } from "@k8slens/kube-api"; import { ServiceApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const serviceApiInjectable = getInjectable({ const serviceApiInjectable = getKubeApiInjectable({
id: "service-api", id: "service-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "serviceApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "serviceApi is only available in certain environments");
@ -20,8 +19,6 @@ const serviceApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default serviceApiInjectable; export default serviceApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { StatefulSetApi } from "@k8slens/kube-api"; import { StatefulSetApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const statefulSetApiInjectable = getInjectable({ const statefulSetApiInjectable = getKubeApiInjectable({
id: "stateful-set-api", id: "stateful-set-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "statefulSetApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "statefulSetApi is only available in certain environments");
@ -20,8 +19,6 @@ const statefulSetApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default statefulSetApiInjectable; export default statefulSetApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { StorageClassApi } from "@k8slens/kube-api"; import { StorageClassApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const storageClassApiInjectable = getInjectable({ const storageClassApiInjectable = getKubeApiInjectable({
id: "storage-class-api", id: "storage-class-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "storageClassApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "storageClassApi is only available in certain environments");
@ -20,8 +19,6 @@ const storageClassApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default storageClassApiInjectable; export default storageClassApiInjectable;

View File

@ -2,26 +2,23 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { ValidatingWebhookConfigurationApi } from "@k8slens/kube-api"; import { ValidatingWebhookConfigurationApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const validatingWebhookConfigurationApiInjectable = getInjectable({ const validatingWebhookConfigurationApiInjectable = getKubeApiInjectable({
id: "validating-webhook-configuration", id: "validating-webhook-configuration-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "validatingWebhookApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "validatingWebhookConfigurationApi is only available in certain environments");
return new ValidatingWebhookConfigurationApi({ return new ValidatingWebhookConfigurationApi({
logger: di.inject(loggerInjectionToken), logger: di.inject(loggerInjectionToken),
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default validatingWebhookConfigurationApiInjectable; export default validatingWebhookConfigurationApiInjectable;

View File

@ -2,15 +2,14 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token"; import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
import { VerticalPodAutoscalerApi } from "@k8slens/kube-api"; import { VerticalPodAutoscalerApi } from "@k8slens/kube-api";
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics"; import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
import { loggerInjectionToken } from "@k8slens/logger"; import { loggerInjectionToken } from "@k8slens/logger";
import maybeKubeApiInjectable from "../maybe-kube-api.injectable"; import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
const verticalPodAutoscalerApiInjectable = getInjectable({ const verticalPodAutoscalerApiInjectable = getKubeApiInjectable({
id: "vertical-pod-autoscaler-api", id: "vertical-pod-autoscaler-api",
instantiate: (di) => { instantiate: (di) => {
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "verticalPodAutoscalerApi is only available in certain environments"); assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "verticalPodAutoscalerApi is only available in certain environments");
@ -20,8 +19,6 @@ const verticalPodAutoscalerApiInjectable = getInjectable({
maybeKubeApi: di.inject(maybeKubeApiInjectable), maybeKubeApi: di.inject(maybeKubeApiInjectable),
}); });
}, },
injectionToken: kubeApiInjectionToken,
}); });
export default verticalPodAutoscalerApiInjectable; export default verticalPodAutoscalerApiInjectable;

View File

@ -97,6 +97,14 @@ export class KubeObjectStore<
private readonly loadedNamespaces = observable.box<string[]>(); private readonly loadedNamespaces = observable.box<string[]>();
static create<Api>(
dependencies: KubeObjectStoreDependencies,
api: Api,
opts?: KubeObjectStoreOptions,
): Api extends KubeApi<infer Kube, infer Data> ? KubeObjectStore<Kube, Api, Data> : never {
return new KubeObjectStore(dependencies, api as KubeApi, opts) as never;
}
constructor( constructor(
protected readonly dependencies: KubeObjectStoreDependencies, protected readonly dependencies: KubeObjectStoreDependencies,
public readonly api: A, public readonly api: A,
@ -297,7 +305,7 @@ export class KubeObjectStore<
return items; return items;
} }
protected resetOnError(error: any) { protected resetOnError(error: unknown) {
if (error) this.reset(); if (error) this.reset();
} }

View File

@ -16,8 +16,8 @@ import type { ReadFile } from "../fs/read-file.injectable";
import { hasTypedProperty, isObject } from "@k8slens/utilities"; import { hasTypedProperty, isObject } from "@k8slens/utilities";
export interface ResourceApplyingStack { export interface ResourceApplyingStack {
kubectlApplyFolder(folderPath: string, templateContext?: any, extraArgs?: string[]): Promise<string>; kubectlApplyFolder(folderPath: string, templateContext?: unknown, extraArgs?: string[]): Promise<string>;
kubectlDeleteFolder(folderPath: string, templateContext?: any, extraArgs?: string[]): Promise<string>; kubectlDeleteFolder(folderPath: string, templateContext?: unknown, extraArgs?: string[]): Promise<string>;
} }
export interface ResourceStackDependencies { export interface ResourceStackDependencies {
@ -41,12 +41,12 @@ export class ResourceStack {
* @param folderPath folder path that is searched for files defining kubernetes resources. * @param folderPath folder path that is searched for files defining kubernetes resources.
* @param templateContext sets the template parameters that are to be applied to any templated kubernetes resources that are to be applied. * @param templateContext sets the template parameters that are to be applied to any templated kubernetes resources that are to be applied.
*/ */
async kubectlApplyFolder(folderPath: string, templateContext?: any, extraArgs?: string[]): Promise<string> { async kubectlApplyFolder(folderPath: string, templateContext?: unknown, extraArgs?: string[]): Promise<string> {
const resources = await this.renderTemplates(folderPath, templateContext); const resources = await this.renderTemplates(folderPath, templateContext);
const result = await this.applyResources(resources, extraArgs); const result = await this.applyResources(resources, extraArgs);
if (result.callWasSuccessful) { if (result.isOk) {
return result.response; return result.value;
} }
this.dependencies.logger.warn(`[RESOURCE-STACK]: failed to apply resources: ${result.error}`); this.dependencies.logger.warn(`[RESOURCE-STACK]: failed to apply resources: ${result.error}`);
@ -59,12 +59,12 @@ export class ResourceStack {
* @param folderPath folder path that is searched for files defining kubernetes resources. * @param folderPath folder path that is searched for files defining kubernetes resources.
* @param templateContext sets the template parameters that are to be applied to any templated kubernetes resources that are to be applied. * @param templateContext sets the template parameters that are to be applied to any templated kubernetes resources that are to be applied.
*/ */
async kubectlDeleteFolder(folderPath: string, templateContext?: any, extraArgs?: string[]): Promise<string> { async kubectlDeleteFolder(folderPath: string, templateContext?: unknown, extraArgs?: string[]): Promise<string> {
const resources = await this.renderTemplates(folderPath, templateContext); const resources = await this.renderTemplates(folderPath, templateContext);
const result = await this.deleteResources(resources, extraArgs); const result = await this.deleteResources(resources, extraArgs);
if (result.callWasSuccessful) { if (result.isOk) {
return result.response; return result.value;
} }
this.dependencies.logger.warn(`[RESOURCE-STACK]: failed to delete resources: ${result.error}`); this.dependencies.logger.warn(`[RESOURCE-STACK]: failed to delete resources: ${result.error}`);
@ -100,7 +100,7 @@ export class ResourceStack {
return []; return [];
} }
protected async renderTemplates(folderPath: string, templateContext: any): Promise<string[]> { protected async renderTemplates(folderPath: string, templateContext: unknown): Promise<string[]> {
const resources: string[] = []; const resources: string[] = [];
const di = getLegacyGlobalDiForExtensionApi(); const di = getLegacyGlobalDiForExtensionApi();
const productName = di.inject(productNameInjectable); const productName = di.inject(productNameInjectable);

View File

@ -7,64 +7,55 @@ import { KubeConfig } from "@kubernetes/client-node";
import yaml from "js-yaml"; import yaml from "js-yaml";
import type { Cluster, Context, User } from "@kubernetes/client-node/dist/config_types"; import type { Cluster, Context, User } from "@kubernetes/client-node/dist/config_types";
import { newClusters, newContexts, newUsers } from "@kubernetes/client-node/dist/config_types"; import { newClusters, newContexts, newUsers } from "@kubernetes/client-node/dist/config_types";
import type { Result } from "@k8slens/utilities";
import { isDefined } from "@k8slens/utilities"; import { isDefined } from "@k8slens/utilities";
import Joi from "joi";
import type { PartialDeep } from "type-fest"; import type { PartialDeep } from "type-fest";
import z from "zod";
import type { ZodError } from "zod";
const clusterSchema = Joi.object({ const userSchema = z.object({
name: Joi name: z.string()
.min(1),
});
const clusterSchema = z.object({
name: z
.string() .string()
.min(1) .min(1),
.required(), cluster: z
cluster: Joi
.object({ .object({
server: Joi server: z
.string() .string()
.min(1) .min(1),
.required(), }),
})
.required(),
}); });
const userSchema = Joi.object({ const contextSchema = z.object({
name: Joi.string() name: z.string()
.min(1) .min(1),
.required(), context: z.object({
}); cluster: z.string()
.min(1),
const contextSchema = Joi.object({ user: z.string()
name: Joi.string() .min(1),
.min(1)
.required(),
context: Joi.object({
cluster: Joi.string()
.min(1)
.required(),
user: Joi.string()
.min(1)
.required(),
}), }),
}); });
const kubeConfigSchema = Joi.object({ const kubeConfigSchema = z.object({
users: Joi users: z
.array() .array(userSchema)
.items(userSchema)
.optional(), .optional(),
clusters: Joi clusters: z
.array() .array(clusterSchema)
.items(clusterSchema)
.optional(), .optional(),
contexts: Joi contexts: z
.array() .array(contextSchema)
.items(contextSchema)
.optional(), .optional(),
"current-context": Joi "current-context": z
.string() .string()
.min(1) .min(1)
.optional(), .optional(),
}) });
.required();
interface KubeConfigOptions { interface KubeConfigOptions {
clusters: Cluster[]; clusters: Cluster[];
@ -73,37 +64,25 @@ interface KubeConfigOptions {
currentContext?: string; currentContext?: string;
} }
interface OptionsResult { function loadToOptions(rawYaml: string): Result<KubeConfigOptions, ZodError<unknown>> {
options: KubeConfigOptions;
error: Joi.ValidationError | undefined;
}
function loadToOptions(rawYaml: string): OptionsResult {
const parsed = yaml.load(rawYaml); const parsed = yaml.load(rawYaml);
const { error } = kubeConfigSchema.validate(parsed, { const configParseResult = kubeConfigSchema.safeParse(parsed);
abortEarly: false,
allowUnknown: true, if (configParseResult.success === false) {
}); return {
const { value } = kubeConfigSchema.validate(parsed, { isOk: false,
abortEarly: false, error: configParseResult.error,
allowUnknown: true, };
stripUnknown: { }
arrays: true,
},
});
const {
clusters: rawClusters,
users: rawUsers,
contexts: rawContexts,
"current-context": currentContext,
} = value ?? {};
const clusters = newClusters(rawClusters);
const users = newUsers(rawUsers);
const contexts = newContexts(rawContexts);
return { return {
options: { clusters, users, contexts, currentContext }, isOk: true,
error, value: {
clusters: newClusters(configParseResult.data.clusters),
users: newUsers(configParseResult.data.users),
contexts: newContexts(configParseResult.data.contexts),
currentContext: configParseResult.data["current-context"],
},
}; };
} }
@ -116,33 +95,32 @@ export function loadFromOptions(options: KubeConfigOptions): KubeConfig {
return kc; return kc;
} }
export interface ConfigResult { export function loadConfigFromString(content: string): Result<KubeConfig, ZodError<unknown>> {
config: KubeConfig; const loadResult = loadToOptions(content);
error: Joi.ValidationError | undefined;
}
export function loadConfigFromString(content: string): ConfigResult { if (loadResult.isOk === false) {
const { options, error } = loadToOptions(content); return loadResult;
}
return { return {
config: loadFromOptions(options), isOk: true,
error, value: loadFromOptions(loadResult.value),
}; };
} }
export function loadValidatedConfig(content: string, contextName: string): ValidateKubeConfigResult { export function loadValidatedConfig(content: string, contextName: string): Result<PartialKubeConfig, ZodError<unknown> | string> {
const { options, error } = loadToOptions(content); const result = loadToOptions(content);
if (error) { if (result.isOk === false) {
return { error }; return result;
} }
return validateKubeConfig(loadFromOptions(options), contextName); return validateKubeConfig(loadFromOptions(result.value), contextName);
} }
export interface SplitConfigEntry { export interface SplitConfigEntry {
config: KubeConfig; config: KubeConfig;
validationResult: ValidateKubeConfigResult; validationResult: Result<PartialKubeConfig, ZodError<unknown> | string>;
} }
/** /**
@ -212,8 +190,8 @@ export function dumpConfigYaml(kubeConfig: PartialDeep<KubeConfig>): string {
"client-certificate": user.certFile, "client-certificate": user.certFile,
"client-key-data": user.keyData, "client-key-data": user.keyData,
"client-key": user.keyFile, "client-key": user.keyFile,
"auth-provider": user.authProvider, "auth-provider": user.authProvider as unknown,
exec: user.exec, exec: user.exec as unknown,
token: user.token, token: user.token,
username: user.username, username: user.username,
password: user.password, password: user.password,
@ -233,26 +211,24 @@ export function dumpConfigYaml(kubeConfig: PartialDeep<KubeConfig>): string {
return yaml.dump(config, { skipInvalid: true }); return yaml.dump(config, { skipInvalid: true });
} }
export type ValidateKubeConfigResult = { export interface PartialKubeConfig {
error: Error; readonly context: Context;
} | { readonly cluster: Cluster;
error?: undefined; readonly user: User;
context: Context; }
cluster: Cluster;
user: User;
};
/** /**
* Checks if `config` has valid `Context`, `User`, `Cluster`, and `exec` fields (if present when required) * Checks if `config` has valid `Context`, `User`, `Cluster`, and `exec` fields (if present when required)
* *
* Note: This function returns an error instead of throwing it, returning `undefined` if the validation passes * Note: This function returns an error instead of throwing it, returning `undefined` if the validation passes
*/ */
export function validateKubeConfig(config: KubeConfig, contextName: string): ValidateKubeConfigResult { export function validateKubeConfig(config: KubeConfig, contextName: string): Result<PartialKubeConfig, string> {
const context = config.getContextObject(contextName); const context = config.getContextObject(contextName);
if (!context) { if (!context) {
return { return {
error: new Error(`No valid context object provided in kubeconfig for context '${contextName}'`), isOk: false,
error: `No valid context object provided in kubeconfig for context '${contextName}'`,
}; };
} }
@ -260,7 +236,8 @@ export function validateKubeConfig(config: KubeConfig, contextName: string): Val
if (!cluster) { if (!cluster) {
return { return {
error: new Error(`No valid cluster object provided in kubeconfig for context '${contextName}'`), isOk: false,
error: `No valid cluster object provided in kubeconfig for context '${contextName}'`,
}; };
} }
@ -268,9 +245,13 @@ export function validateKubeConfig(config: KubeConfig, contextName: string): Val
if (!user) { if (!user) {
return { return {
error: new Error(`No valid user object provided in kubeconfig for context '${contextName}'`), isOk: false,
error: `No valid user object provided in kubeconfig for context '${contextName}'`,
}; };
} }
return { cluster, user, context }; return {
isOk: true,
value: { cluster, user, context },
};
} }

View File

@ -2,13 +2,15 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import type { AsyncResult } from "@k8slens/utilities";
import type { KubeConfig } from "@kubernetes/client-node";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { ZodError } from "zod";
import readFileInjectable from "../fs/read-file.injectable"; import readFileInjectable from "../fs/read-file.injectable";
import type { ConfigResult } from "../kube-helpers";
import { loadConfigFromString } from "../kube-helpers"; import { loadConfigFromString } from "../kube-helpers";
import resolveTildeInjectable from "../path/resolve-tilde.injectable"; import resolveTildeInjectable from "../path/resolve-tilde.injectable";
export type LoadConfigFromFile = (filePath: string) => Promise<ConfigResult>; export type LoadConfigFromFile = (filePath: string) => AsyncResult<KubeConfig, ZodError<unknown>>;
const loadConfigFromFileInjectable = getInjectable({ const loadConfigFromFileInjectable = getInjectable({
id: "load-config-from-file", id: "load-config-from-file",

Some files were not shown because too many files have changed in this diff Show More