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

Ensure that all mentioned items in extension API are exported

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-02-28 08:34:45 -05:00
parent 1077a949ec
commit 33de7cf7e9
118 changed files with 1761 additions and 894 deletions

View File

@ -1,12 +1,12 @@
name: Check Documentation name: Check Documentation
on: on:
pull_request: pull_request:
types: [opened, labeled, unlabeled, synchronize] branches:
- "**"
jobs: jobs:
build: build:
name: Check Docs name: Check Docs
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ contains(github.event.pull_request.labels.*.name, 'area/documentation') }}
strategy: strategy:
matrix: matrix:
node-version: [14.x] node-version: [14.x]

View File

@ -41,6 +41,7 @@
"lint:fix": "yarn run lint --fix", "lint:fix": "yarn run lint --fix",
"mkdocs-serve-local": "docker build -t mkdocs-serve-local:latest mkdocs/ && docker run --rm -it -p 8000:8000 -v ${PWD}:/docs mkdocs-serve-local:latest", "mkdocs-serve-local": "docker build -t mkdocs-serve-local:latest mkdocs/ && docker run --rm -it -p 8000:8000 -v ${PWD}:/docs mkdocs-serve-local:latest",
"verify-docs": "docker build -t mkdocs-serve-local:latest mkdocs/ && docker run --rm -v ${PWD}:/docs mkdocs-serve-local:latest build --strict", "verify-docs": "docker build -t mkdocs-serve-local:latest mkdocs/ && docker run --rm -v ${PWD}:/docs mkdocs-serve-local:latest build --strict",
"preverify-docs": "yarn run typedocs-extensions-api",
"typedocs-extensions-api": "yarn run typedoc src/extensions/extension-api.ts", "typedocs-extensions-api": "yarn run typedoc src/extensions/extension-api.ts",
"version-checkout": "cat package.json | jq '.version' -r | xargs printf \"release/v%s\" | xargs git checkout -b", "version-checkout": "cat package.json | jq '.version' -r | xargs printf \"release/v%s\" | xargs git checkout -b",
"version-commit": "cat package.json | jq '.version' -r | xargs printf \"release v%s\" | git commit --no-edit -s -F -", "version-commit": "cat package.json | jq '.version' -r | xargs printf \"release v%s\" | git commit --no-edit -s -F -",

View File

@ -7,7 +7,7 @@ import { navigate } from "../../renderer/navigation";
import { CatalogCategory, CatalogEntity, CatalogEntityMetadata, CatalogEntitySpec, CatalogEntityStatus } from "../catalog"; import { CatalogCategory, CatalogEntity, CatalogEntityMetadata, CatalogEntitySpec, CatalogEntityStatus } from "../catalog";
import { catalogCategoryRegistry } from "../catalog/catalog-category-registry"; import { catalogCategoryRegistry } from "../catalog/catalog-category-registry";
interface GeneralEntitySpec extends CatalogEntitySpec { export interface GeneralEntitySpec extends CatalogEntitySpec {
path: string; path: string;
icon?: { icon?: {
material?: string; material?: string;

View File

@ -130,10 +130,14 @@ export class KubernetesCluster<
catalogCategoryRegistry catalogCategoryRegistry
.getCategoryForEntity<KubernetesClusterCategory>(this) .getCategoryForEntity<KubernetesClusterCategory>(this)
?.emit("contextMenuOpen", this, context); .emit("contextMenuOpen", this, context);
} }
} }
/**
* The category for {@link KubernetesCluster}'s. Not constructable, use
* {@link kubernetesClusterCategory} to register event handlers.
*/
class KubernetesClusterCategory extends CatalogCategory { class KubernetesClusterCategory extends CatalogCategory {
public readonly apiVersion = "catalog.k8slens.dev/v1alpha1"; public readonly apiVersion = "catalog.k8slens.dev/v1alpha1";
public readonly kind = "CatalogCategory"; public readonly kind = "CatalogCategory";
@ -155,6 +159,7 @@ class KubernetesClusterCategory extends CatalogCategory {
}; };
} }
export type { KubernetesClusterCategory };
export const kubernetesClusterCategory = new KubernetesClusterCategory(); export const kubernetesClusterCategory = new KubernetesClusterCategory();
catalogCategoryRegistry.add(kubernetesClusterCategory); catalogCategoryRegistry.add(kubernetesClusterCategory);

View File

@ -4,16 +4,29 @@
*/ */
import { action, computed, observable, makeObservable } from "mobx"; import { action, computed, observable, makeObservable } from "mobx";
import { type Disposer, strictSet, iter, getOrInsertMap } from "../utils";
import { CatalogCategory, CatalogEntity, CatalogEntityData, CatalogEntityKindData } from "./catalog-entity";
import { once } from "lodash"; import { once } from "lodash";
import { iter, getOrInsertMap, strictSet } from "../utils";
import type { Disposer } from "../utils";
import { CatalogCategory, CatalogEntityData, CatalogEntityKindData } from "./catalog-entity";
export type CategoryFilter = (category: CatalogCategory) => any; export type CategoryFilter = (category: CatalogCategory) => any;
/**
* The registry of declared categories in the renderer
*/
export class CatalogCategoryRegistry { export class CatalogCategoryRegistry {
/**
* @internal
*/
protected categories = observable.set<CatalogCategory>(); protected categories = observable.set<CatalogCategory>();
/**
* @internal
*/
protected groupKinds = new Map<string, Map<string, CatalogCategory>>(); protected groupKinds = new Map<string, Map<string, CatalogCategory>>();
/**
* @internal
*/
protected filters = observable.set<CategoryFilter>([], { protected filters = observable.set<CategoryFilter>([], {
deep: false, deep: false,
}); });
@ -22,6 +35,12 @@ export class CatalogCategoryRegistry {
makeObservable(this); makeObservable(this);
} }
/**
* Attempt to add a new category to the registry.
* @param category The category instance to add
* @returns A function to deregister the instance
* @throws If there already exists a previous category that declared as specific group and kind
*/
@action add(category: CatalogCategory): Disposer { @action add(category: CatalogCategory): Disposer {
const byGroup = getOrInsertMap(this.groupKinds, category.spec.group); const byGroup = getOrInsertMap(this.groupKinds, category.spec.group);
@ -34,10 +53,16 @@ export class CatalogCategoryRegistry {
}; };
} }
/**
* Get a list of all the categories that are currently registered
*/
@computed get items() { @computed get items() {
return Array.from(this.categories); return Array.from(this.categories);
} }
/**
* Get a list of all the categories that match all the registered filters
*/
@computed get filteredItems() { @computed get filteredItems() {
return Array.from( return Array.from(
iter.reduce( iter.reduce(
@ -48,12 +73,22 @@ export class CatalogCategoryRegistry {
); );
} }
/**
* Attempt to get a category but the api group and kind it declared
* @param group The group string of the desired category
* @param kind The name that a category declares
*/
getForGroupKind<T extends CatalogCategory>(group: string, kind: string): T | undefined { getForGroupKind<T extends CatalogCategory>(group: string, kind: string): T | undefined {
return this.groupKinds.get(group)?.get(kind) as T; return this.groupKinds.get(group)?.get(kind) as T;
} }
getEntityForData(data: CatalogEntityData & CatalogEntityKindData) { /**
* Create a new entity instance from `data` or return `null` if cannot find category
* @param data The data to create the instance from
* @param data.apiVersion Used to find the category by group and version
* @param data.kind Used to find the category for a specific kind
*/
getEntityForData(data: CatalogEntityData & CatalogEntityKindData): CatalogEntity | null {
const category = this.getCategoryForEntity(data); const category = this.getCategoryForEntity(data);
if (!category) { if (!category) {
@ -72,14 +107,24 @@ export class CatalogCategoryRegistry {
return new specVersion.entityClass(data); return new specVersion.entityClass(data);
} }
getCategoryForEntity<T extends CatalogCategory>(data: CatalogEntityData & CatalogEntityKindData): T | undefined { /**
* Try and find a category by its version declarations
* @param data The `apiVersion` and `kind` that was declared by a category
* @returns The category instance if found
*/
getCategoryForEntity<T extends CatalogCategory>(data: CatalogEntityKindData): T | undefined {
const splitApiVersion = data.apiVersion.split("/"); const splitApiVersion = data.apiVersion.split("/");
const group = splitApiVersion[0]; const group = splitApiVersion[0];
return this.getForGroupKind(group, data.kind); return this.getForGroupKind(group, data.kind);
} }
getByName(name: string) { /**
* Try and find a category by the name is was registered with
* @param name The name of the category
* @returns The category instance if found
*/
getByName(name: string): CatalogCategory | undefined {
return this.items.find(category => category.metadata?.name == name); return this.items.find(category => category.metadata?.name == name);
} }

View File

@ -10,9 +10,9 @@ import { once } from "lodash";
import { iter, Disposer } from "../utils"; import { iter, Disposer } from "../utils";
import type { CategoryColumnRegistration } from "../../renderer/components/+catalog/custom-category-columns"; import type { CategoryColumnRegistration } from "../../renderer/components/+catalog/custom-category-columns";
type ExtractEntityMetadataType<Entity> = Entity extends CatalogEntity<infer Metadata> ? Metadata : never; export type ExtractEntityMetadataType<Entity> = Entity extends CatalogEntity<infer Metadata> ? Metadata : never;
type ExtractEntityStatusType<Entity> = Entity extends CatalogEntity<any, infer Status> ? Status : never; export type ExtractEntityStatusType<Entity> = Entity extends CatalogEntity<any, infer Status> ? Status : never;
type ExtractEntitySpecType<Entity> = Entity extends CatalogEntity<any, any, infer Spec> ? Spec : never; export type ExtractEntitySpecType<Entity> = Entity extends CatalogEntity<any, any, infer Spec> ? Spec : never;
export type CatalogEntityConstructor<Entity extends CatalogEntity> = ( export type CatalogEntityConstructor<Entity extends CatalogEntity> = (
(new (data: CatalogEntityData< (new (data: CatalogEntityData<
@ -88,26 +88,35 @@ export interface CatalogCategorySpec {
*/ */
export type AddMenuFilter = (menu: CatalogEntityAddMenu) => any; export type AddMenuFilter = (menu: CatalogEntityAddMenu) => any;
/**
* The events that can be emitted onto a catalog category
*/
export interface CatalogCategoryEvents { export interface CatalogCategoryEvents {
/** /**
* This event will be emitted when the category is loaded in the catalog * An event which is emitted when the category becomes active on the catalog
* view. * view.
*/ */
load: () => void; load: () => void;
/** /**
* This event will be emitted when the catalog add menu is opened and is the * An event which is emitted when the menu for adding new catalog entities
* way to added entries to that menu. * is opened.
* @param context The event context
*/ */
catalogAddMenu: (context: CatalogEntityAddMenuContext) => void; catalogAddMenu: (context: CatalogEntityAddMenuContext) => void;
/** /**
* This event will be emitted when the context menu for an entity is declared * An event which is emitted when the context menu on a entity versioned by
* by this category is opened. * this category is opened.
* @param entity The entity that was opened
* @param context The event context
*/ */
contextMenuOpen: (entity: CatalogEntity, context: CatalogEntityContextMenuContext) => void; contextMenuOpen: (entity: CatalogEntity, context: CatalogEntityContextMenuContext) => void;
} }
/**
* A declartion of supported versions a specific kind of CatalogEntity
*/
export abstract class CatalogCategory extends (EventEmitter as new () => TypedEmitter<CatalogCategoryEvents>) { export abstract class CatalogCategory extends (EventEmitter as new () => TypedEmitter<CatalogCategoryEvents>) {
/** /**
* The version of category that you are wanting to declare. * The version of category that you are wanting to declare.
@ -210,6 +219,9 @@ export interface CatalogEntityMetadata {
[key: string]: string | object; [key: string]: string | object;
} }
/**
* The minimal information that all entities must use to describe their current status
*/
export interface CatalogEntityStatus { export interface CatalogEntityStatus {
phase: string; phase: string;
reason?: string; reason?: string;
@ -222,59 +234,104 @@ export interface CatalogEntityStatus {
active?: boolean; active?: boolean;
} }
/**
* The event context for when an entity is activated
*/
export interface CatalogEntityActionContext { export interface CatalogEntityActionContext {
navigate: (url: string) => void; /**
setCommandPaletteContext: (context?: CatalogEntity) => void; * A function to navigate around the application
* @param pathname The path to navigate to
*/
navigate: (pathname: string) => void;
/**
* A function to change the active entity for the command palette
*/
setCommandPaletteContext: (entity?: CatalogEntity) => void;
} }
/**
* The descriptor for entities' context menus and detail panels' topbars
*/
export interface CatalogEntityContextMenu { export interface CatalogEntityContextMenu {
/** /**
* Menu title * When in a context menu, the text displayed
*/ */
title: string; title: string;
/** /**
* Menu icon * When in a toolbar the icon's material or svg data
*
* If not present then this item will not be displayed in the toolbar
*/ */
icon?: string; icon?: string;
/** /**
* OnClick handler * The function that will be called when the menu item is clicked
*/ */
onClick: () => void | Promise<void>; onClick: () => void | Promise<void>;
/** /**
* Confirm click with a message * If present then a confirmation dialog will be displayed to the user with
* the given message before the `onClick` handler is called.
*/ */
confirm?: { confirm?: {
message: string; message: string;
}; };
} }
/**
* The context type for the add menu event in the catalog view
*/
export interface CatalogEntityAddMenu extends CatalogEntityContextMenu { export interface CatalogEntityAddMenu extends CatalogEntityContextMenu {
/**
* The icon's material or svg data for the menu item.
*/
icon: string; icon: string;
/**
* If this menu item should be the default action. If multiple items are
* declared as the default one then none are executed.
*/
defaultAction?: boolean; defaultAction?: boolean;
} }
export interface CatalogEntitySettingsMenu { /**
group?: string; * The context type for entity context menus and drawer detail topbar menus
title: string; */
components: {
View: React.ComponentType<any>;
};
}
export interface CatalogEntityContextMenuContext { export interface CatalogEntityContextMenuContext {
/** /**
* Navigate to the specified pathname * A function to navigate around the application
* @param pathname The path to navigate to
*/ */
navigate: (pathname: string) => void; navigate: (pathname: string) => void;
/**
* The output array of items
*/
menuItems: CatalogEntityContextMenu[]; menuItems: CatalogEntityContextMenu[];
} }
/**
* @deprecated Not used
*/
export interface CatalogEntitySettingsContext { export interface CatalogEntitySettingsContext {
/**
* The output array of items
*/
menuItems: CatalogEntityContextMenu[]; menuItems: CatalogEntityContextMenu[];
} }
export interface CatalogEntityAddMenuContext { export interface CatalogEntityAddMenuContext {
/**
* A function to navigate around the application
* @param pathname The path to navigate to
*/
navigate: (url: string) => void; navigate: (url: string) => void;
/**
* The output array of items
*/
menuItems: CatalogEntityAddMenu[]; menuItems: CatalogEntityAddMenu[];
} }
@ -336,14 +393,14 @@ export abstract class CatalogEntity<
} }
/** /**
* Get the UID of this entity * A convenience function for getting the entity ID
*/ */
public getId(): string { public getId(): string {
return this.metadata.uid; return this.metadata.uid;
} }
/** /**
* Get the name of this entity * A convenience function for getting the entity name
*/ */
public getName(): string { public getName(): string {
return this.metadata.name; return this.metadata.name;
@ -364,7 +421,18 @@ export abstract class CatalogEntity<
return this.status.enabled ?? true; return this.status.enabled ?? true;
} }
/**
* The function that will be called when the entity is activated
*/
public abstract onRun?(context: CatalogEntityActionContext): void | Promise<void>; public abstract onRun?(context: CatalogEntityActionContext): void | Promise<void>;
public abstract onContextMenuOpen(context: CatalogEntityContextMenuContext): void | Promise<void>;
public abstract onSettingsOpen(context: CatalogEntitySettingsContext): void | Promise<void>; /**
* The function that is called when the context menu is opened for a specific entity
*/
public abstract onContextMenuOpen?(context: CatalogEntityContextMenuContext): void | Promise<void>;
/**
* @deprecated This is not used. Use the `RenderExtension.entitySettings` field instead
*/
public abstract onSettingsOpen?(context: CatalogEntitySettingsContext): void | Promise<void>;
} }

View File

@ -3,32 +3,75 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
// Custom event emitter /**
* The options for when adding a new listener
*/
export interface AddListenerOptions {
/**
* Should the listener only ever receive one event.
*
* @default false
*/
once?: boolean;
interface Options { /**
once?: boolean; // call once and remove * If `true` then the listener will be put to the front of the event queue
prepend?: boolean; // put listener to the beginning *
* @default false
*/
prepend?: boolean;
} }
type Callback<D extends [...any[]]> = (...data: D) => void | boolean; /**
* A function for handling events. If the function returns `false` then no
* further listeners will be called for that event.
*/
export type EventListener<D extends any[]> = (...data: D) => void | boolean;
export class EventEmitter<D extends [...any[]]> { /**
protected listeners: [Callback<D>, Options][] = []; * An event emitter for a single event. Generic over the arguments for the
* event handler.
*/
export class EventEmitter<D extends any[]> {
protected listeners = new Map<EventListener<D>, Required<Omit<AddListenerOptions, "prepend">>>();
addListener(callback: Callback<D>, options: Options = {}) { /**
const fn = options.prepend ? "unshift" : "push"; * Add a new listener for this event emitter
* @param callback The function to call when an event is emitted.
* @param options Options for controlling how the listener is handled.
*/
addListener(callback: EventListener<D>, options?: AddListenerOptions) {
const { prepend, once = false } = options ?? {};
this.listeners[fn]([callback, options]); if (prepend) {
this.listeners = new Map([
[callback, { once }],
...this.listeners.entries(),
]);
} else {
this.listeners.set(callback, { once });
}
} }
removeListener(callback: Callback<D>) { /**
this.listeners = this.listeners.filter(([cb]) => cb !== callback); * Removes `callback` from being called for future events.
* @param callback The listener instance to remove
*/
removeListener(callback: EventListener<D>) {
this.listeners.delete(callback);
} }
/**
* Removes all current listeners.
*/
removeAllListeners() { removeAllListeners() {
this.listeners.length = 0; this.listeners.clear();
} }
/**
* Emits a new event.
* @param data The event data
*/
emit = (...data: D) => { emit = (...data: D) => {
for (const [callback, { once }] of this.listeners) { for (const [callback, { once }] of this.listeners) {
if (once) { if (once) {

View File

@ -7,6 +7,9 @@ import orderBy from "lodash/orderBy";
import { autoBind } from "./utils"; import { autoBind } from "./utils";
import { action, computed, observable, when, makeObservable } from "mobx"; import { action, computed, observable, when, makeObservable } from "mobx";
/**
* An object whose ID and name can be gotten via methods.
*/
export interface ItemObject { export interface ItemObject {
getId(): string; getId(): string;
getName(): string; getName(): string;

View File

@ -29,7 +29,7 @@ describe("Crds", () => {
storage: false, storage: false,
}, },
], ],
}, } as CustomResourceDefinitionSpec,
}); });
expect(() => crd.getVersion()).toThrowError("Failed to find a version for CustomResourceDefinition foo"); expect(() => crd.getVersion()).toThrowError("Failed to find a version for CustomResourceDefinition foo");
@ -57,7 +57,7 @@ describe("Crds", () => {
storage: false, storage: false,
}, },
], ],
}, } as CustomResourceDefinitionSpec,
}); });
expect(crd.getVersion()).toBe("123"); expect(crd.getVersion()).toBe("123");
@ -85,7 +85,7 @@ describe("Crds", () => {
storage: false, storage: false,
}, },
], ],
}, } as CustomResourceDefinitionSpec,
}); });
expect(crd.getVersion()).toBe("123"); expect(crd.getVersion()).toBe("123");
@ -114,7 +114,7 @@ describe("Crds", () => {
storage: false, storage: false,
}, },
], ],
}, } as CustomResourceDefinitionSpec,
}); });
expect(crd.getVersion()).toBe("123"); expect(crd.getVersion()).toBe("123");

View File

@ -11,82 +11,137 @@ import type { KubeApi } from "./kube-api";
import type { KubeObject } from "./kube-object"; import type { KubeObject } from "./kube-object";
import { IKubeObjectRef, parseKubeApi, createKubeApiURL } from "./kube-api-parse"; import { IKubeObjectRef, parseKubeApi, createKubeApiURL } from "./kube-api-parse";
/**
* The manager of registered kube apis and KubeObject stores
*/
export class ApiManager { export class ApiManager {
private apis = observable.map<string, KubeApi<KubeObject>>(); private apis = observable.map<string, KubeApi<KubeObject>>();
private stores = observable.map<string, KubeObjectStore<KubeObject>>(); private stores = observable.map<KubeApi<KubeObject>, KubeObjectStore<KubeObject>>();
/**
* @internal
*/
constructor() { constructor() {
makeObservable(this); makeObservable(this);
autoBind(this); autoBind(this);
} }
getApi(pathOrCallback: string | ((api: KubeApi<KubeObject>) => boolean)) { /**
* Get the KubeApi instance which either has registered under the given
* path or by the apiBase of the given path or the first api which the
* callback returns `true` for.
* @param pathOrCallback Either the api path or a matching function
*/
getApi(pathOrCallback: string | ((api: KubeApi<KubeObject>) => boolean)): KubeApi<KubeObject> | undefined {
if (typeof pathOrCallback === "string") { if (typeof pathOrCallback === "string") {
return this.apis.get(pathOrCallback) || this.apis.get(parseKubeApi(pathOrCallback).apiBase); return this.apis.get(pathOrCallback) || this.apis.get(parseKubeApi(pathOrCallback).apiBase);
} }
return iter.find(this.apis.values(), pathOrCallback ?? (() => true)); return iter.find(this.apis.values(), pathOrCallback);
} }
getApiByKind(kind: string, apiVersion: string) { /**
return iter.find(this.apis.values(), api => api.kind === kind && api.apiVersionWithGroup === apiVersion); * Get the `KubeApi` instance which is for the kube resource `kind` under the
* apiVersion and group `apiVersion`
*
* Example:
* ```ts
* this.getApiByKind("Pod", "api/v1");
* ```
* @param kind The kube resource kind
* @param apiVersion The kube apiVersion and group
*/
getApiByKind(kind: string, apiVersion: string): KubeApi<KubeObject> | undefined {
return this.getApi(api => api.kind === kind && api.apiVersionWithGroup === apiVersion);
} }
registerApi(apiBase: string, api: KubeApi<KubeObject>) { /**
if (!api.apiBase) return; * Attempt to register `api` under `apiBase`. If `apiBase` already has been
* registered then this function does nothing.
if (!this.apis.has(apiBase)) { * @param apiBase The kube resource api base to register the api against
this.stores.forEach((store) => { * @param api The `KubeApi` instance to register
if (store.api === api) { */
this.stores.set(apiBase, store); registerApi(apiBase: string, api: KubeApi<KubeObject>): void {
if (!api.apiBase || this.apis.has(apiBase)) {
return;
} }
});
this.apis.set(apiBase, api); this.apis.set(apiBase, api);
} }
}
protected resolveApi<K extends KubeObject>(api?: string | KubeApi<K>): KubeApi<K> | undefined { /**
if (!api) { * Unifies apiBases and instances into instances
* @param apiOrBase Either the `apiBase` string or the `KubeApi` instance
*/
protected resolveApi<K extends KubeObject>(apiOrBase: string | KubeApi<K>): KubeApi<K> | undefined {
if (!apiOrBase) {
return undefined; return undefined;
} }
if (typeof api === "string") { if (typeof apiOrBase === "string") {
return this.getApi(api) as KubeApi<K>; return this.getApi(apiOrBase) as KubeApi<K>;
} }
return api; return apiOrBase;
} }
unregisterApi(api: string | KubeApi<KubeObject>) { /**
if (typeof api === "string") this.apis.delete(api); * Removes
else { * @param apiOrBase Either an apiBase string or the instance to deregister
const apis = Array.from(this.apis.entries()); */
const entry = apis.find(entry => entry[1] === api); unregisterApi(apiOrBase: string | KubeApi<KubeObject>) {
if (typeof apiOrBase === "string") {
if (entry) this.unregisterApi(entry[0]); this.apis.delete(apiOrBase);
} else {
for (const [apiBase, api] of this.apis) {
if (api === apiOrBase) {
this.apis.delete(apiBase);
}
}
} }
} }
/**
* Register a store under its api's apiBase
* @param store The store instance to register
*/
registerStore(store: KubeObjectStore<KubeObject>): void;
/**
* @deprecated Use {@link ApiManager.registerStore} instead as a store should
* only be registered under its own api
*/
registerStore(store: KubeObjectStore<KubeObject>, apis: KubeApi<KubeObject>[]): void;
@action @action
registerStore(store: KubeObjectStore<KubeObject>, apis: KubeApi<KubeObject>[] = [store.api]) { registerStore(store: KubeObjectStore<KubeObject>, apis?: KubeApi<KubeObject>[]): void {
apis.filter(Boolean).forEach(api => { if (apis) {
if (api.apiBase) this.stores.set(api.apiBase, store); for (const api of apis) {
}); this.stores.set(api, store);
}
} else {
this.stores.set(store.api, store);
}
} }
getStore<S extends KubeObjectStore<KubeObject>>(api: string | KubeApi<KubeObject>): S | undefined { /**
return this.stores.get(this.resolveApi(api)?.apiBase) as S; * Get the registered store under the provided key
* @param apiOrBase Either the apiBase or a KubeApi instance
*/
getStore<S extends KubeObjectStore<KubeObject>>(apiOrBase: string | KubeApi<KubeObject>): S | undefined {
return this.stores.get(this.resolveApi(apiOrBase)) as S;
} }
/**
* Attempt to get the api string for a given kube resource
* @param ref An object describing the kube resource
* @param parentObject Used to get the namespace or the resource if `ref` does not provided it
* @returns The kube API resource string
*/
lookupApiLink(ref: IKubeObjectRef, parentObject?: KubeObject): string { lookupApiLink(ref: IKubeObjectRef, parentObject?: KubeObject): string {
const { const {
kind, apiVersion, name, kind, apiVersion, name,
namespace = parentObject?.getNs(), namespace = parentObject?.getNs(),
} = ref; } = ref;
if (!kind) return "";
// search in registered apis by 'kind' & 'apiVersion' // search in registered apis by 'kind' & 'apiVersion'
const api = this.getApi(api => api.kind === kind && api.apiVersionWithGroup == apiVersion); const api = this.getApi(api => api.kind === kind && api.apiVersionWithGroup == apiVersion);
@ -119,4 +174,7 @@ export class ApiManager {
} }
} }
/**
* The single instance per frame.
*/
export const apiManager = new ApiManager(); export const apiManager = new ApiManager();

View File

@ -3,7 +3,7 @@
* 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 { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
export type ClusterRoleBindingSubjectKind = "Group" | "ServiceAccount" | "User"; export type ClusterRoleBindingSubjectKind = "Group" | "ServiceAccount" | "User";
@ -39,16 +39,20 @@ export class ClusterRoleBinding extends KubeObject {
} }
/** /**
* Only available within kubernetes cluster pages * The api type for {@link ClusterRoleBinding}'s
*/ */
let clusterRoleBindingApi: KubeApi<ClusterRoleBinding>; export class ClusterRoleBindingApi extends KubeApi<ClusterRoleBinding> {
constructor(params?: BaseKubeApiOptions) {
if (isClusterPageContext()) { super({
clusterRoleBindingApi = new KubeApi({ ...(params ?? {}),
objectConstructor: ClusterRoleBinding, objectConstructor: ClusterRoleBinding,
}); });
}
} }
export { /**
clusterRoleBindingApi, * Only available within kubernetes cluster pages
}; */
export const clusterRoleBindingApi = isClusterPageContext()
? new ClusterRoleBindingApi()
: undefined;

View File

@ -4,7 +4,7 @@
*/ */
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
export interface ClusterRole { export interface ClusterRole {
@ -27,16 +27,20 @@ export class ClusterRole extends KubeObject {
} }
/** /**
* Only available within kubernetes cluster pages * The api type for {@link ClusterRole}'s
*/ */
let clusterRoleApi: KubeApi<ClusterRole>; export class ClusterRoleApi extends KubeApi<ClusterRole> {
constructor(params?: BaseKubeApiOptions) {
if (isClusterPageContext()) { // initialize automatically only when within a cluster iframe/context super({
clusterRoleApi = new KubeApi({ ...(params ?? {}),
objectConstructor: ClusterRole, objectConstructor: ClusterRole,
}); });
}
} }
export { /**
clusterRoleApi, * Only available within kubernetes cluster pages
}; */
export const clusterRoleApi = isClusterPageContext()
? new ClusterRoleApi()
: undefined;

View File

@ -110,14 +110,8 @@ export class Cluster extends KubeObject {
/** /**
* Only available within kubernetes cluster pages * Only available within kubernetes cluster pages
*/ */
let clusterApi: ClusterApi; export const clusterApi = isClusterPageContext()
? new ClusterApi({
if (isClusterPageContext()) { // initialize automatically only when within a cluster iframe/context
clusterApi = new ClusterApi({
objectConstructor: Cluster, objectConstructor: Cluster,
}); })
} : undefined;
export {
clusterApi,
};

View File

@ -5,7 +5,7 @@
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import { autoBind } from "../../utils"; import { autoBind } from "../../utils";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
@ -32,17 +32,18 @@ export class ConfigMap extends KubeObject {
} }
} }
export class ConfigMapApi extends KubeApi<ConfigMap> {
constructor(params?: BaseKubeApiOptions) {
super({
...(params ?? {}),
objectConstructor: ConfigMap,
});
}
}
/** /**
* Only available within kubernetes cluster pages * Only available within kubernetes cluster pages
*/ */
let configMapApi: KubeApi<ConfigMap>; export const configMapApi = isClusterPageContext()
? new ConfigMapApi()
if (isClusterPageContext()) { : undefined;
configMapApi = new KubeApi({
objectConstructor: ConfigMap,
});
}
export {
configMapApi,
};

View File

@ -3,13 +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 { KubeCreationError, KubeObject } from "../kube-object"; import { KubeObject, KubeObjectMetadata } from "../kube-object";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import { crdResourcesURL } from "../../routes"; import { crdResourcesURL } from "../../routes";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
import type { KubeJsonApiData } from "../kube-json-api";
interface AdditionalPrinterColumnsCommon { export interface AdditionalPrinterColumnsCommon {
name: string; name: string;
type: "integer" | "number" | "string" | "boolean" | "date"; type: "integer" | "number" | "string" | "boolean" | "date";
priority: number; priority: number;
@ -20,7 +19,7 @@ export type AdditionalPrinterColumnsV1 = AdditionalPrinterColumnsCommon & {
jsonPath: string; jsonPath: string;
}; };
type AdditionalPrinterColumnsV1Beta = AdditionalPrinterColumnsCommon & { export type AdditionalPrinterColumnsV1Beta = AdditionalPrinterColumnsCommon & {
JSONPath: string; JSONPath: string;
}; };
@ -79,25 +78,35 @@ export interface CustomResourceDefinition {
}; };
storedVersions: string[]; storedVersions: string[];
}; };
/**
* @deprecated for apiextensions.k8s.io/v1 but used previously
*/
additionalPrinterColumns?: AdditionalPrinterColumnsV1Beta[];
} }
export interface CRDApiData extends KubeJsonApiData { export interface CustomResourceDefinitionStatus {
spec: object; // TODO: make better conditions: {
lastTransitionTime: string;
message: string;
reason: string;
status: string;
type?: string;
}[];
acceptedNames: {
plural: string;
singular: string;
kind: string;
shortNames: string[];
listKind: string;
};
storedVersions: string[];
} }
export class CustomResourceDefinition extends KubeObject { export class CustomResourceDefinition extends KubeObject<KubeObjectMetadata, CustomResourceDefinitionStatus, CustomResourceDefinitionSpec> {
static kind = "CustomResourceDefinition"; static kind = "CustomResourceDefinition";
static namespaced = false; static namespaced = false;
static apiBase = "/apis/apiextensions.k8s.io/v1/customresourcedefinitions"; static apiBase = "/apis/apiextensions.k8s.io/v1/customresourcedefinitions";
constructor(data: CRDApiData) {
super(data);
if (!data.spec || typeof data.spec !== "object") {
throw new KubeCreationError("Cannot create a CustomResourceDefinition from an object without spec", data);
}
}
getResourceUrl() { getResourceUrl() {
return crdResourcesURL({ return crdResourcesURL({
params: { params: {
@ -211,17 +220,21 @@ export class CustomResourceDefinition extends KubeObject {
} }
/** /**
* Only available within kubernetes cluster pages * The api type for {@link CustomResourceDefinition}'s
*/ */
let crdApi: KubeApi<CustomResourceDefinition>; export class CustomResourceDefinitionApi extends KubeApi<CustomResourceDefinition> {
constructor(params?: Pick<BaseKubeApiOptions, "request">) {
if (isClusterPageContext()) { super({
crdApi = new KubeApi<CustomResourceDefinition>({ ...(params ?? {}),
objectConstructor: CustomResourceDefinition, objectConstructor: CustomResourceDefinition,
checkPreferredVersion: true, checkPreferredVersion: true,
}); });
}
} }
export { /**
crdApi, * Only available within kubernetes cluster pages
}; */
export const crdApi = isClusterPageContext()
? new CustomResourceDefinitionApi()
: undefined;

View File

@ -128,14 +128,8 @@ export class CronJob extends KubeObject {
/** /**
* Only available within kubernetes cluster pages * Only available within kubernetes cluster pages
*/ */
let cronJobApi: CronJobApi; export const cronJobApi = isClusterPageContext()
? new CronJobApi({
if (isClusterPageContext()) {
cronJobApi = new CronJobApi({
objectConstructor: CronJob, objectConstructor: CronJob,
}); })
} : undefined;
export {
cronJobApi,
};

View File

@ -103,14 +103,8 @@ export function getMetricsForDaemonSets(daemonsets: DaemonSet[], namespace: stri
/** /**
* Only available within kubernetes cluster pages * Only available within kubernetes cluster pages
*/ */
let daemonSetApi: DaemonSetApi; export const daemonSetApi = isClusterPageContext()
? new DaemonSetApi({
if (isClusterPageContext()) {
daemonSetApi = new DaemonSetApi({
objectConstructor: DaemonSet, objectConstructor: DaemonSet,
}); })
} : undefined;
export {
daemonSetApi,
};

View File

@ -77,7 +77,7 @@ export function getMetricsForDeployments(deployments: Deployment[], namespace: s
}); });
} }
interface IContainerProbe { export interface IContainerProbe {
httpGet?: { httpGet?: {
path?: string; path?: string;
port: number; port: number;
@ -224,14 +224,11 @@ export class Deployment extends WorkloadKubeObject {
} }
} }
let deploymentApi: DeploymentApi; /**
* Only available within kubernetes cluster pages
if (isClusterPageContext()) { */
deploymentApi = new DeploymentApi({ export const deploymentApi = isClusterPageContext()
? new DeploymentApi({
objectConstructor: Deployment, objectConstructor: Deployment,
}); })
} : undefined;
export {
deploymentApi,
};

View File

@ -5,7 +5,7 @@
import { autoBind } from "../../utils"; import { autoBind } from "../../utils";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { get } from "lodash"; import { get } from "lodash";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
@ -28,7 +28,7 @@ export interface IEndpointSubset {
ports: IEndpointPort[]; ports: IEndpointPort[];
} }
interface ITargetRef { export interface ITargetRef {
kind: string; kind: string;
namespace: string; namespace: string;
name: string; name: string;
@ -131,17 +131,23 @@ export class Endpoint extends KubeObject {
return "<none>"; return "<none>";
} }
} }
} }
let endpointApi: KubeApi<Endpoint>; /**
* The api type for {@link Endpoint}'s
if (isClusterPageContext()) { */
endpointApi = new KubeApi<Endpoint>({ export class EndpointApi extends KubeApi<Endpoint> {
constructor(params?: BaseKubeApiOptions) {
super({
...(params ?? {}),
objectConstructor: Endpoint, objectConstructor: Endpoint,
}); });
}
} }
export { /**
endpointApi, * Only available within kubernetes cluster pages
}; */
export const endpointApi = isClusterPageContext()
? new EndpointApi()
: undefined;

View File

@ -6,7 +6,7 @@
import moment from "moment"; import moment from "moment";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { formatDuration } from "../../utils/formatDuration"; import { formatDuration } from "../../utils/formatDuration";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
export interface KubeEvent { export interface KubeEvent {
@ -62,14 +62,22 @@ export class KubeEvent extends KubeObject {
} }
} }
let eventApi: KubeApi<KubeEvent>; /**
* The api type for {@link KubeEvent}'s
*/
if (isClusterPageContext()) { export class KubeEventApi extends KubeApi<KubeEvent> {
eventApi = new KubeApi<KubeEvent>({ constructor(params?: BaseKubeApiOptions) {
super({
...(params ?? {}),
objectConstructor: KubeEvent, objectConstructor: KubeEvent,
}); });
}
} }
export { /**
eventApi, * Only available within kubernetes cluster pages
}; */
export const eventApi = isClusterPageContext()
? new KubeEventApi()
: undefined;

View File

@ -4,7 +4,7 @@
*/ */
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
export enum HpaMetricType { export enum HpaMetricType {
@ -148,14 +148,21 @@ export class HorizontalPodAutoscaler extends KubeObject {
} }
} }
let hpaApi: KubeApi<HorizontalPodAutoscaler>; /**
* The api type for {@link HorizontalPodAutoscaler}'s
if (isClusterPageContext()) { */
hpaApi = new KubeApi<HorizontalPodAutoscaler>({ export class HorizontalPodAutoscalerApi extends KubeApi<HorizontalPodAutoscaler> {
constructor(params?: BaseKubeApiOptions) {
super({
...(params ?? {}),
objectConstructor: HorizontalPodAutoscaler, objectConstructor: HorizontalPodAutoscaler,
}); });
}
} }
export { /**
hpaApi, * Only available within kubernetes cluster pages
}; */
export const hpaApi = isClusterPageContext()
? new HorizontalPodAutoscalerApi()
: undefined;

View File

@ -40,14 +40,18 @@ export interface ILoadBalancerIngress {
ip?: string; ip?: string;
} }
// extensions/v1beta1 /**
interface IExtensionsBackend { * For use when Ingresses are under `extensions/v1beta1`
*/
export interface IExtensionsBackend {
serviceName: string; serviceName: string;
servicePort: number | string; servicePort: number | string;
} }
// networking.k8s.io/v1 /**
interface INetworkingBackend { * For use when Ingresses are under `networking.k8s.io/v1`
*/
export interface INetworkingBackend {
service: IIngressService; service: IIngressService;
} }
@ -194,17 +198,14 @@ export class Ingress extends KubeObject {
} }
} }
let ingressApi: IngressApi; /**
* Only available within kubernetes cluster pages
if (isClusterPageContext()) { */
ingressApi = new IngressApi({ export const ingressApi = isClusterPageContext()
? new IngressApi({
objectConstructor: Ingress, objectConstructor: Ingress,
// Add fallback for Kubernetes <1.19 // Add fallback for Kubernetes <1.19
checkPreferredVersion: true, checkPreferredVersion: true,
fallbackApiBases: ["/apis/extensions/v1beta1/ingresses"], fallbackApiBases: ["/apis/extensions/v1beta1/ingresses"],
}); })
} : undefined;
export {
ingressApi,
};

View File

@ -123,14 +123,11 @@ export function getMetricsForJobs(jobs: Job[], namespace: string, selector = "")
}); });
} }
let jobApi: JobApi; /**
* Only available within kubernetes cluster pages
if (isClusterPageContext()) { */
jobApi = new JobApi({ export const jobApi = isClusterPageContext()
? new JobApi({
objectConstructor: Job, objectConstructor: Job,
}); })
} : undefined;
export {
jobApi,
};

View File

@ -4,7 +4,7 @@
*/ */
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import { autoBind } from "../../utils"; import { autoBind } from "../../utils";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
@ -65,14 +65,21 @@ export class LimitRange extends KubeObject {
} }
} }
let limitRangeApi: KubeApi<LimitRange>; /**
* The api type for {@link LimitRange}'s
if (isClusterPageContext()) { */
limitRangeApi = new KubeApi<LimitRange>({ export class LimitRangeApi extends KubeApi<LimitRange> {
constructor(params?: BaseKubeApiOptions) {
super({
...(params ?? {}),
objectConstructor: LimitRange, objectConstructor: LimitRange,
}); });
}
} }
export { /**
limitRangeApi, * Only available within kubernetes cluster pages
}; */
export const limitRangeApi = isClusterPageContext()
? new LimitRangeApi()
: undefined;

View File

@ -56,14 +56,11 @@ export function getMetricsForNamespace(namespace: string, selector = ""): Promis
}); });
} }
let namespacesApi: NamespaceApi; /**
* Only available within kubernetes cluster pages
if (isClusterPageContext()) { */
namespacesApi = new NamespaceApi({ export const namespacesApi = isClusterPageContext()
? new NamespaceApi({
objectConstructor: Namespace, objectConstructor: Namespace,
}); })
} : undefined;
export {
namespacesApi,
};

View File

@ -5,7 +5,7 @@
import { KubeObject, LabelSelector } from "../kube-object"; import { KubeObject, LabelSelector } from "../kube-object";
import { autoBind } from "../../utils"; import { autoBind } from "../../utils";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
@ -129,14 +129,22 @@ export class NetworkPolicy extends KubeObject {
} }
} }
let networkPolicyApi: KubeApi<NetworkPolicy>; /**
* The api type for {@link NetworkPolicy}'s
*/
if (isClusterPageContext()) { export class NetworkPolicyApi extends KubeApi<NetworkPolicy> {
networkPolicyApi = new KubeApi<NetworkPolicy>({ constructor(params?: BaseKubeApiOptions) {
super({
...(params ?? {}),
objectConstructor: NetworkPolicy, objectConstructor: NetworkPolicy,
}); });
}
} }
export { /**
networkPolicyApi, * Only available within kubernetes cluster pages
}; */
export const networkPolicyApi = isClusterPageContext()
? new NetworkPolicyApi()
: undefined;

View File

@ -249,14 +249,11 @@ export class Node extends KubeObject {
} }
} }
let nodesApi: NodesApi; /**
* Only available within kubernetes cluster pages
if (isClusterPageContext()) { */
nodesApi = new NodesApi({ export const nodesApi = isClusterPageContext()
? new NodesApi({
objectConstructor: Node, objectConstructor: Node,
}); })
} : undefined;
export {
nodesApi,
};

View File

@ -94,14 +94,11 @@ export class PersistentVolumeClaim extends KubeObject {
} }
} }
let pvcApi: PersistentVolumeClaimsApi; /**
* Only available within kubernetes cluster pages
if (isClusterPageContext()) { */
pvcApi = new PersistentVolumeClaimsApi({ export const pvcApi = isClusterPageContext()
? new PersistentVolumeClaimsApi({
objectConstructor: PersistentVolumeClaim, objectConstructor: PersistentVolumeClaim,
}); })
} : undefined;
export {
pvcApi,
};

View File

@ -5,7 +5,7 @@
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { autoBind, unitsToBytes } from "../../utils"; import { autoBind, unitsToBytes } from "../../utils";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
@ -86,14 +86,22 @@ export class PersistentVolume extends KubeObject {
} }
} }
let persistentVolumeApi: KubeApi<PersistentVolume>; /**
* The api type for {@link PersistentVolume}'s
*/
if (isClusterPageContext()) { export class PersistentVolumeApi extends KubeApi<PersistentVolume> {
persistentVolumeApi = new KubeApi({ constructor(params?: BaseKubeApiOptions) {
super({
...(params ?? {}),
objectConstructor: PersistentVolume, objectConstructor: PersistentVolume,
}); });
}
} }
export { /**
persistentVolumeApi, * Only available within kubernetes cluster pages
}; */
export const persistentVolumeApi = isClusterPageContext()
? new PersistentVolumeApi()
: undefined;

View File

@ -25,14 +25,11 @@ export class PodMetrics extends KubeObject {
static apiBase = "/apis/metrics.k8s.io/v1beta1/pods"; static apiBase = "/apis/metrics.k8s.io/v1beta1/pods";
} }
let podMetricsApi: KubeApi<PodMetrics>; /**
* Only available within kubernetes cluster pages
if (isClusterPageContext()) { */
podMetricsApi = new KubeApi<PodMetrics>({ export const podMetricsApi = isClusterPageContext()
? new KubeApi<PodMetrics>({
objectConstructor: PodMetrics, objectConstructor: PodMetrics,
}); })
} : undefined;
export {
podMetricsApi,
};

View File

@ -5,7 +5,7 @@
import { autoBind } from "../../utils"; import { autoBind } from "../../utils";
import { KubeObject, LabelSelector } from "../kube-object"; import { KubeObject, LabelSelector } from "../kube-object";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
@ -54,17 +54,23 @@ export class PodDisruptionBudget extends KubeObject {
getDesiredHealthy() { getDesiredHealthy() {
return this.status.desiredHealthy; return this.status.desiredHealthy;
} }
} }
let pdbApi: KubeApi<PodDisruptionBudget>; /**
* The api type for {@link PodDisruptionBudget}'s
if (isClusterPageContext()) { */
pdbApi = new KubeApi({ export class PodDisruptionBudgetApi extends KubeApi<PodDisruptionBudget> {
constructor(params?: BaseKubeApiOptions) {
super({
...(params ?? {}),
objectConstructor: PodDisruptionBudget, objectConstructor: PodDisruptionBudget,
}); });
}
} }
export { /**
pdbApi, * Only available within kubernetes cluster pages
}; */
export const pdbApi = isClusterPageContext()
? new PodDisruptionBudgetApi()
: undefined;

View File

@ -73,7 +73,7 @@ export enum PodStatus {
EVICTED = "Evicted", EVICTED = "Evicted",
} }
export interface IPodContainer extends Partial<Record<PodContainerProbe, IContainerProbe>> { export interface IPodContainer extends Partial<Record<PodContainerProbe, ContainerProbe>> {
name: string; name: string;
image: string; image: string;
command?: string[]; command?: string[];
@ -129,7 +129,7 @@ export interface IPodContainer extends Partial<Record<PodContainerProbe, IContai
export type PodContainerProbe = "livenessProbe" | "readinessProbe" | "startupProbe"; export type PodContainerProbe = "livenessProbe" | "readinessProbe" | "startupProbe";
interface IContainerProbe { export interface ContainerProbe {
httpGet?: { httpGet?: {
path?: string; path?: string;
@ -501,14 +501,11 @@ export class Pod extends WorkloadKubeObject {
} }
} }
let podsApi: PodsApi; /**
* Only available within kubernetes cluster pages
if (isClusterPageContext()) { */
podsApi = new PodsApi({ export const podsApi = isClusterPageContext()
? new PodsApi({
objectConstructor: Pod, objectConstructor: Pod,
}); })
} : undefined;
export {
podsApi,
};

View File

@ -102,14 +102,11 @@ export class PodSecurityPolicy extends KubeObject {
} }
} }
let pspApi: KubeApi<PodSecurityPolicy>; /**
* Only available within kubernetes cluster pages
if (isClusterPageContext()) { */
pspApi = new KubeApi({ export const pspApi = isClusterPageContext()
? new KubeApi<PodSecurityPolicy>({
objectConstructor: PodSecurityPolicy, objectConstructor: PodSecurityPolicy,
}); })
} : undefined;
export {
pspApi,
};

View File

@ -111,14 +111,11 @@ export class ReplicaSet extends WorkloadKubeObject {
} }
} }
let replicaSetApi: ReplicaSetApi; /**
* Only available within kubernetes cluster pages
if (isClusterPageContext()) { */
replicaSetApi = new ReplicaSetApi({ export const replicaSetApi = isClusterPageContext()
? new ReplicaSetApi({
objectConstructor: ReplicaSet, objectConstructor: ReplicaSet,
}); })
} : undefined;
export {
replicaSetApi,
};

View File

@ -4,7 +4,7 @@
*/ */
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
export interface IResourceQuotaValues { export interface IResourceQuotaValues {
@ -65,14 +65,23 @@ export class ResourceQuota extends KubeObject {
} }
} }
let resourceQuotaApi: KubeApi<ResourceQuota>; /**
* The api type for {@link ResourceQuota}'s
*/
if (isClusterPageContext()) { export class ResourceQuotaApi extends KubeApi<ResourceQuota> {
resourceQuotaApi = new KubeApi<ResourceQuota>({ constructor(params?: BaseKubeApiOptions) {
super({
...(params ?? {}),
objectConstructor: ResourceQuota, objectConstructor: ResourceQuota,
}); });
}
} }
export { /**
resourceQuotaApi, * Only available within kubernetes cluster pages
}; */
export const resourceQuotaApi = isClusterPageContext()
? new ResourceQuotaApi()
: undefined;

View File

@ -5,7 +5,7 @@
import { autoBind } from "../../utils"; import { autoBind } from "../../utils";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
@ -46,14 +46,22 @@ export class RoleBinding extends KubeObject {
} }
} }
let roleBindingApi: KubeApi<RoleBinding>; /**
* The api type for {@link RoleBinding}'s
*/
if (isClusterPageContext()) { export class RoleBindingApi extends KubeApi<RoleBinding> {
roleBindingApi = new KubeApi({ constructor(params?: BaseKubeApiOptions) {
super({
...(params ?? {}),
objectConstructor: RoleBinding, objectConstructor: RoleBinding,
}); });
}
} }
export { /**
roleBindingApi, * Only available within kubernetes cluster pages
}; */
export const roleBindingApi = isClusterPageContext()
? new RoleBindingApi()
: undefined;

View File

@ -4,7 +4,7 @@
*/ */
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
export interface Role { export interface Role {
@ -26,14 +26,23 @@ export class Role extends KubeObject {
} }
} }
let roleApi: KubeApi<Role>; /**
* The api type for {@link Role}'s
*/
if (isClusterPageContext()) { export class RoleApi extends KubeApi<Role> {
roleApi = new KubeApi<Role>({ constructor(params?: BaseKubeApiOptions) {
super({
...(params ?? {}),
objectConstructor: Role, objectConstructor: Role,
}); });
}
} }
export{ /**
roleApi, * Only available within kubernetes cluster pages
}; */
export const roleApi = isClusterPageContext()
? new RoleApi()
: undefined;

View File

@ -6,7 +6,7 @@
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { autoBind } from "../../utils"; import { autoBind } from "../../utils";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
export enum SecretType { export enum SecretType {
@ -54,14 +54,21 @@ export class Secret extends KubeObject {
} }
} }
let secretsApi: KubeApi<Secret>; /**
* The api type for {@link Secret}'s
if (isClusterPageContext()) { */
secretsApi = new KubeApi({ export class SecretApi extends KubeApi<Secret> {
constructor(params?: BaseKubeApiOptions) {
super({
...(params ?? {}),
objectConstructor: Secret, objectConstructor: Secret,
}); });
}
} }
export { /**
secretsApi, * Only available within kubernetes cluster pages
}; */
export const secretsApi = isClusterPageContext()
? new SecretApi()
: undefined;

View File

@ -71,15 +71,12 @@ export class SelfSubjectRulesReview extends KubeObject {
} }
} }
let selfSubjectRulesReviewApi: SelfSubjectRulesReviewApi; /**
* Only available within kubernetes cluster pages
if (isClusterPageContext()) { */
selfSubjectRulesReviewApi = new SelfSubjectRulesReviewApi({ export const selfSubjectRulesReviewApi = isClusterPageContext()
? new SelfSubjectRulesReviewApi({
objectConstructor: SelfSubjectRulesReview, objectConstructor: SelfSubjectRulesReview,
}); })
} : undefined;
export {
selfSubjectRulesReviewApi,
};

View File

@ -5,7 +5,7 @@
import { autoBind } from "../../utils"; import { autoBind } from "../../utils";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
@ -37,14 +37,22 @@ export class ServiceAccount extends KubeObject {
} }
} }
let serviceAccountsApi: KubeApi<ServiceAccount>; /**
* The api type for {@link ServiceAccount}'s
*/
if (isClusterPageContext()) { export class ServiceAccountApi extends KubeApi<ServiceAccount> {
serviceAccountsApi = new KubeApi<ServiceAccount>({ constructor(params?: BaseKubeApiOptions) {
super({
...(params ?? {}),
objectConstructor: ServiceAccount, objectConstructor: ServiceAccount,
}); });
}
} }
export { /**
serviceAccountsApi, * Only available within kubernetes cluster pages
}; */
export const serviceAccountsApi = isClusterPageContext()
? new ServiceAccountApi()
: undefined;

View File

@ -5,7 +5,7 @@
import { autoBind } from "../../../renderer/utils"; import { autoBind } from "../../../renderer/utils";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
@ -132,14 +132,21 @@ export class Service extends KubeObject {
} }
} }
let serviceApi: KubeApi<Service>; /**
* The api type for {@link Service}'s
if (isClusterPageContext()) { */
serviceApi = new KubeApi<Service>({ export class ServiceApi extends KubeApi<Service> {
constructor(params?: BaseKubeApiOptions) {
super({
...(params ?? {}),
objectConstructor: Service, objectConstructor: Service,
}); });
}
} }
export { /**
serviceApi, * Only available within kubernetes cluster pages
}; */
export const serviceApi = isClusterPageContext()
? new ServiceApi()
: undefined;

View File

@ -136,14 +136,11 @@ export class StatefulSet extends WorkloadKubeObject {
} }
} }
let statefulSetApi: StatefulSetApi; /**
* Only available within kubernetes cluster pages
if (isClusterPageContext()) { */
statefulSetApi = new StatefulSetApi({ export const statefulSetApi = isClusterPageContext()
? new StatefulSetApi({
objectConstructor: StatefulSet, objectConstructor: StatefulSet,
}); })
} : undefined;
export {
statefulSetApi,
};

View File

@ -5,7 +5,7 @@
import { autoBind } from "../../utils"; import { autoBind } from "../../utils";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { BaseKubeApiOptions, KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
@ -47,14 +47,22 @@ export class StorageClass extends KubeObject {
} }
} }
let storageClassApi: KubeApi<StorageClass>; /**
* The api type for {@link StorageClass}'s
*/
if (isClusterPageContext()) { export class StorageClassApi extends KubeApi<StorageClass> {
storageClassApi = new KubeApi({ constructor(params?: BaseKubeApiOptions) {
super({
...(params ?? {}),
objectConstructor: StorageClass, objectConstructor: StorageClass,
}); });
}
} }
export { /**
storageClassApi, * Only available within kubernetes cluster pages
}; */
export const storageClassApi = isClusterPageContext()
? new StorageClassApi()
: undefined;

View File

@ -9,8 +9,7 @@ import { apiKubePrefix, apiPrefix, isDebugging, isDevelopment } from "../../comm
import { isClusterPageContext } from "../utils/cluster-id-url-parsing"; import { isClusterPageContext } from "../utils/cluster-id-url-parsing";
import { appEventBus } from "../app-event-bus/event-bus"; import { appEventBus } from "../app-event-bus/event-bus";
let apiBase: JsonApi; export let apiBase: JsonApi;
let apiKube: KubeJsonApi;
if (typeof window === "undefined") { if (typeof window === "undefined") {
appEventBus.addListener((event) => { appEventBus.addListener((event) => {
@ -42,8 +41,11 @@ if (typeof window === "undefined") {
}); });
} }
if (isClusterPageContext()) { /**
apiKube = new KubeJsonApi({ * Only available within kubernetes cluster pages
*/
export const apiKube = isClusterPageContext()
? new KubeJsonApi({
serverAddress: `http://127.0.0.1:${window.location.port}`, serverAddress: `http://127.0.0.1:${window.location.port}`,
apiBase: apiKubePrefix, apiBase: apiKubePrefix,
debug: isDevelopment, debug: isDevelopment,
@ -51,10 +53,5 @@ if (isClusterPageContext()) {
headers: { headers: {
"Host": window.location.host, "Host": window.location.host,
}, },
}); })
} : undefined;
export {
apiBase,
apiKube,
};

View File

@ -44,6 +44,9 @@ export interface JsonApiConfig {
const httpAgent = new HttpAgent({ keepAlive: true }); const httpAgent = new HttpAgent({ keepAlive: true });
const httpsAgent = new HttpsAgent({ keepAlive: true }); const httpsAgent = new HttpsAgent({ keepAlive: true });
/**
* The base type used for communicating with a JSON returning API server
*/
export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> { export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
static reqInitDefault: RequestInit = { static reqInitDefault: RequestInit = {
headers: { headers: {
@ -199,6 +202,9 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
} }
} }
/**
* The pseudo-error type that is throw when there are errors from a request
*/
export class JsonApiErrorParsed { export class JsonApiErrorParsed {
isUsedForNotification = false; isUsedForNotification = false;

View File

@ -12,7 +12,7 @@ import { inspect } from "util";
export interface IKubeObjectRef { export interface IKubeObjectRef {
kind: string; kind: string;
apiVersion: string; apiVersion?: string;
name: string; name: string;
namespace?: string; namespace?: string;
} }

View File

@ -23,16 +23,10 @@ import { Agent, AgentOptions } from "https";
import type { Patch } from "rfc6902"; import type { Patch } from "rfc6902";
/** /**
* The options used for creating a `KubeApi` * The base constructor options for {@link KubeApi} for use with child classes
* of it.
*/ */
export interface IKubeApiOptions<T extends KubeObject> { export interface BaseKubeApiOptions {
/**
* base api-path for listing all resources, e.g. "/api/v1/pods"
*
* If not specified then will be the one on the `objectConstructor`
*/
apiBase?: string;
/** /**
* If the API uses a different API endpoint (e.g. apiBase) depending on the cluster version, * If the API uses a different API endpoint (e.g. apiBase) depending on the cluster version,
* fallback API bases can be listed individually. * fallback API bases can be listed individually.
@ -47,17 +41,29 @@ export interface IKubeApiOptions<T extends KubeObject> {
*/ */
checkPreferredVersion?: boolean; checkPreferredVersion?: boolean;
/**
* The constructor for the kube objects returned from the API
*/
objectConstructor: KubeObjectConstructor<T>;
/** /**
* The api instance to use for making requests * The api instance to use for making requests
* *
* @default apiKube * @default apiKube
*/ */
request?: KubeJsonApi; request?: KubeJsonApi;
}
/**
* The options used for creating a `KubeApi`
*/
export interface IKubeApiOptions<T extends KubeObject> extends BaseKubeApiOptions {
/**
* The constructor for the kube objects returned from the API
*/
objectConstructor: KubeObjectConstructor<T>;
/**
* base api-path for listing all resources, e.g. "/api/v1/pods"
*
* @deprecated It should be specified on the `objectConstructor`
*/
apiBase?: string;
/** /**
* @deprecated should be specified by `objectConstructor` * @deprecated should be specified by `objectConstructor`
@ -290,7 +296,7 @@ export class KubeApi<T extends KubeObject> {
this.objectConstructor = objectConstructor; this.objectConstructor = objectConstructor;
this.parseResponse = this.parseResponse.bind(this); this.parseResponse = this.parseResponse.bind(this);
apiManager.registerApi(apiBase, this); apiManager.registerApi(this.apiBase, this);
} }
get apiVersionWithGroup() { get apiVersionWithGroup() {

View File

@ -3,7 +3,7 @@
* 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 { JsonApi, JsonApiData, JsonApiError } from "./json-api"; import { JsonApi, JsonApiError } from "./json-api";
import type { Response } from "node-fetch"; import type { Response } from "node-fetch";
import { LensProxy } from "../../main/lens-proxy"; import { LensProxy } from "../../main/lens-proxy";
import { apiKubePrefix, isDebugging } from "../vars"; import { apiKubePrefix, isDebugging } from "../vars";
@ -38,10 +38,12 @@ export interface KubeJsonApiMetadata {
[key: string]: any; [key: string]: any;
} }
export interface KubeJsonApiData extends JsonApiData { export interface KubeJsonApiData<Metadata extends KubeJsonApiMetadata = KubeJsonApiMetadata, Status = {}, Spec = {}> {
kind: string; kind: string;
apiVersion: string; apiVersion: string;
metadata: KubeJsonApiMetadata; metadata: Metadata;
status?: Status;
spec?: Spec;
} }
export interface KubeJsonApiError extends JsonApiError { export interface KubeJsonApiError extends JsonApiError {

View File

@ -57,7 +57,10 @@ export interface KubeObjectStoreSubscribeParams {
} }
export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T> { export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T> {
static defaultContext = observable.box<ClusterContext>(); // TODO: support multiple cluster contexts /**
* @internal
*/
static defaultContext: ClusterContext; // TODO: support multiple cluster contexts
public api: KubeApi<T>; public api: KubeApi<T>;
public readonly limit?: number; public readonly limit?: number;
@ -81,8 +84,11 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
this.bindWatchEventsUpdater(); this.bindWatchEventsUpdater();
} }
/**
* @internal
*/
get context(): ClusterContext { get context(): ClusterContext {
return KubeObjectStore.defaultContext.get(); return KubeObjectStore.defaultContext;
} }
// TODO: Circular dependency: KubeObjectStore -> ClusterFrameContext -> NamespaceStore -> KubeObjectStore // TODO: Circular dependency: KubeObjectStore -> ClusterFrameContext -> NamespaceStore -> KubeObjectStore
@ -369,11 +375,10 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
return Promise.all(this.selectedItems.map(this.remove)); return Promise.all(this.selectedItems.map(this.remove));
} }
async removeItems(items: T[]) { /**
await Promise.all(items.map(this.remove)); * collect items from watch-api events to avoid UI blowing up with huge streams of data
} * @internal
*/
// collect items from watch-api events to avoid UI blowing up with huge streams of data
protected eventsBuffer = observable.array<IKubeWatchEvent<KubeJsonApiData>>([], { deep: false }); protected eventsBuffer = observable.array<IKubeWatchEvent<KubeJsonApiData>>([], { deep: false });
protected bindWatchEventsUpdater(delay = 1000) { protected bindWatchEventsUpdater(delay = 1000) {

View File

@ -14,6 +14,7 @@ import type { JsonApiParams } from "./json-api";
import * as resourceApplierApi from "./endpoints/resource-applier.api"; import * as resourceApplierApi from "./endpoints/resource-applier.api";
import { hasOptionalProperty, hasTypedProperty, isObject, isString, bindPredicate, isTypedArray, isRecord } from "../../common/utils/type-narrowing"; import { hasOptionalProperty, hasTypedProperty, isObject, isString, bindPredicate, isTypedArray, isRecord } from "../../common/utils/type-narrowing";
import type { Patch } from "rfc6902"; import type { Patch } from "rfc6902";
import Joi from "joi";
export type KubeObjectConstructor<K extends KubeObject> = (new (data: KubeJsonApiData | any) => K) & { export type KubeObjectConstructor<K extends KubeObject> = (new (data: KubeJsonApiData | any) => K) & {
kind?: string; kind?: string;
@ -25,9 +26,9 @@ export interface KubeObjectMetadata {
uid: string; uid: string;
name: string; name: string;
namespace?: string; namespace?: string;
creationTimestamp: string; creationTimestamp?: string;
resourceVersion: string; resourceVersion: string;
selfLink: string; selfLink?: string;
deletionTimestamp?: string; deletionTimestamp?: string;
finalizers?: string[]; finalizers?: string[];
continue?: string; // provided when used "?limit=" query param to fetch objects list continue?: string; // provided when used "?limit=" query param to fetch objects list
@ -116,6 +117,36 @@ export interface LabelSelector {
matchExpressions?: LabelMatchExpression[]; matchExpressions?: LabelMatchExpression[];
} }
const kubeObjectValidator = Joi
.object({
metadata: Joi
.object()
.unknown(true)
.required(),
spec: Joi.
object()
.unknown(true)
.optional(),
status: Joi.
object()
.unknown(true)
.optional(),
managedFields: Joi.
object()
.unknown(true)
.optional(),
apiVersion: Joi
.string()
.required(),
kind: Joi
.string()
.required(),
})
.unknown(true);
/**
* The Lens representation of a kube resource
*/
export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata, Status = any, Spec = any> implements ItemObject { export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata, Status = any, Spec = any> implements ItemObject {
static readonly kind?: string; static readonly kind?: string;
static readonly namespaced?: boolean; static readonly namespaced?: boolean;
@ -126,7 +157,7 @@ export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata
metadata: Metadata; metadata: Metadata;
status?: Status; status?: Status;
spec?: Spec; spec?: Spec;
managedFields?: any; managedFields?: object;
static create(data: KubeJsonApiData) { static create(data: KubeJsonApiData) {
return new KubeObject(data); return new KubeObject(data);
@ -227,13 +258,11 @@ export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata
...KubeObject.nonEditablePathPrefixes, ...KubeObject.nonEditablePathPrefixes,
]); ]);
constructor(data: KubeJsonApiData) { constructor(data: KubeJsonApiData<Metadata, Status, Spec>) {
if (typeof data !== "object") { const { error } = kubeObjectValidator.validate(data);
throw new TypeError(`Cannot create a KubeObject from ${typeof data}`);
}
if (!data.metadata || typeof data.metadata !== "object") { if (error) {
throw new KubeCreationError(`Cannot create a KubeObject from an object without metadata`, data); throw error;
} }
Object.assign(this, data); Object.assign(this, data);

View File

@ -14,13 +14,18 @@ export interface IToleration {
tolerationSeconds?: number; tolerationSeconds?: number;
} }
interface IMatchExpression { export interface Affinity<T> {
requiredDuringSchedulingIgnoredDuringExecution?: T[];
preferredDuringSchedulingIgnoredDuringExecution?: T[];
}
export interface IMatchExpression {
key: string; key: string;
operator: string; operator: string;
values: string[]; values: string[];
} }
interface INodeAffinity { export interface INodeAffinity {
nodeSelectorTerms?: { nodeSelectorTerms?: {
matchExpressions: IMatchExpression[]; matchExpressions: IMatchExpression[];
}[]; }[];
@ -30,7 +35,7 @@ interface INodeAffinity {
}; };
} }
interface IPodAffinity { export interface IPodAffinity {
labelSelector: { labelSelector: {
matchExpressions: IMatchExpression[]; matchExpressions: IMatchExpression[];
}; };
@ -38,18 +43,9 @@ interface IPodAffinity {
} }
export interface IAffinity { export interface IAffinity {
nodeAffinity?: { nodeAffinity?: Affinity<INodeAffinity>;
requiredDuringSchedulingIgnoredDuringExecution?: INodeAffinity[]; podAffinity?: Affinity<IPodAffinity>;
preferredDuringSchedulingIgnoredDuringExecution?: INodeAffinity[]; podAntiAffinity?: Affinity<IPodAffinity>;
};
podAffinity?: {
requiredDuringSchedulingIgnoredDuringExecution?: IPodAffinity[];
preferredDuringSchedulingIgnoredDuringExecution?: IPodAffinity[];
};
podAntiAffinity?: {
requiredDuringSchedulingIgnoredDuringExecution?: IPodAffinity[];
preferredDuringSchedulingIgnoredDuringExecution?: IPodAffinity[];
};
} }
export class WorkloadKubeObject extends KubeObject { export class WorkloadKubeObject extends KubeObject {

View File

@ -10,6 +10,8 @@ export function noop<T extends any[]>(...args: T): void {
return void args; return void args;
} }
export type Defaulted<Params, DefaultParams extends keyof Params> = Required<Pick<Params, DefaultParams>> & Omit<Params, DefaultParams>;
export * from "./abort-controller"; export * from "./abort-controller";
export * from "./app-version"; export * from "./app-version";
export * from "./autobind"; export * from "./autobind";

View File

@ -1,45 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { Injectable, TentativeTuple } from "@ogre-tools/injectable";
import { getLegacyGlobalDiForExtensionApi } from "./legacy-global-di-for-extension-api";
type MapInjectables<T> = {
[Key in keyof T]: T[Key] extends () => infer Res ? Res : never;
};
export const asLegacyGlobalObjectForExtensionApiWithModifications = <
TInjectable extends Injectable<unknown, unknown, TInstantiationParameter>,
TInstantiationParameter,
OtherFields extends Record<string, () => any>,
>(
injectableKey: TInjectable,
otherFields: OtherFields,
...instantiationParameter: TentativeTuple<TInstantiationParameter>
) =>
new Proxy(
{},
{
get(target, propertyName) {
if (propertyName === "$$typeof") {
return undefined;
}
const instance: any = getLegacyGlobalDiForExtensionApi().inject(
injectableKey,
...instantiationParameter,
);
const propertyValue = instance[propertyName] ?? otherFields[propertyName as any]();
if (typeof propertyValue === "function") {
return function (...args: any[]) {
return propertyValue.apply(instance, args);
};
}
return propertyValue;
},
},
) as ReturnType<TInjectable["instantiate"]> & MapInjectables<OtherFields>;

View File

@ -9,16 +9,22 @@ export {
GeneralEntity, GeneralEntity,
WebLink, WebLink,
} from "../../common/catalog-entities"; } from "../../common/catalog-entities";
export type { export type {
KubernetesClusterPrometheusMetrics, KubernetesClusterPrometheusMetrics,
KubernetesClusterSpec, KubernetesClusterSpec,
KubernetesClusterCategory,
KubernetesClusterMetadata, KubernetesClusterMetadata,
WebLinkSpec, WebLinkSpec,
WebLinkStatus, WebLinkStatus,
WebLinkStatusPhase, WebLinkStatusPhase,
KubernetesClusterStatusPhase, KubernetesClusterStatusPhase,
KubernetesClusterStatus, KubernetesClusterStatus,
GeneralEntitySpec,
} from "../../common/catalog-entities"; } from "../../common/catalog-entities";
export type {
CategoryFilter,
} from "../../common/catalog/catalog-category-registry";
export * from "../../common/catalog/catalog-entity"; export * from "../../common/catalog/catalog-entity";
export { CatalogRunEvent } from "../../common/catalog/catalog-run-event";

View File

@ -5,3 +5,4 @@
export { appEventBus } from "../../common/app-event-bus/event-bus"; export { appEventBus } from "../../common/app-event-bus/event-bus";
export type { AppEvent } from "../../common/app-event-bus/event-bus"; export type { AppEvent } from "../../common/app-event-bus/event-bus";
export type { EventEmitter, AddListenerOptions, EventListener } from "../../common/event-emitter";

View File

@ -2,13 +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.
*/ */
export type { StatusBarRegistration } from "../../renderer/components/status-bar/status-bar-registration"; export type { StatusBarRegistration, StatusBarComponents, StatusBarItemProps } from "../../renderer/components/status-bar/status-bar-registration";
export type { KubeObjectMenuRegistration, KubeObjectMenuComponents } from "../../renderer/components/kube-object-menu/dependencies/kube-object-menu-items/kube-object-menu-registration"; export type { KubeObjectMenuRegistration, KubeObjectMenuComponents, KubeObjectMenuItemProps } from "../../renderer/components/kube-object-menu/dependencies/kube-object-menu-items/kube-object-menu-registration";
export type { AppPreferenceRegistration, AppPreferenceComponents } from "../../renderer/components/+preferences/app-preferences/app-preference-registration"; export type { AppPreferenceRegistration, AppPreferenceComponents } from "../../renderer/components/+preferences/app-preferences/app-preference-registration";
export type { KubeObjectDetailRegistration, KubeObjectDetailComponents } from "../registries/kube-object-detail-registry"; export type { KubeObjectDetailRegistration, KubeObjectDetailComponents } from "../registries/kube-object-detail-registry";
export type { KubeObjectStatusRegistration } from "../registries/kube-object-status-registry"; export type { KubeObjectStatusRegistration } from "../registries/kube-object-status-registry";
export type { PageRegistration, RegisteredPage, PageParams, PageComponentProps, PageComponents, PageTarget } from "../registries/page-registry"; export type { PageRegistration, RegisteredPage, PageParams, PageComponentProps, PageComponents, PageTarget } from "../registries/page-registry";
export type { ClusterPageMenuRegistration, ClusterPageMenuComponents } from "../registries/page-menu-registry"; export type { ClusterPageMenuRegistration, ClusterPageMenuComponents } from "../registries/page-menu-registry";
export type { ProtocolHandlerRegistration, RouteParams as ProtocolRouteParams, RouteHandler as ProtocolRouteHandler } from "../registries/protocol-handler"; export type { MenuRegistration } from "../../main/menu/menu-registration";
export type { MenuTopId } from "../../main/menu/menu";
export type { CatalogEntityDetailRegistration, CatalogEntityDetailsProps, CatalogEntityDetailComponents } from "../registries/catalog-entity-detail-registry";
export type { CustomCategoryViewProps, CustomCategoryViewComponents, CustomCategoryViewRegistration } from "../../renderer/components/+catalog/custom-views"; export type { CustomCategoryViewProps, CustomCategoryViewComponents, CustomCategoryViewRegistration } from "../../renderer/components/+catalog/custom-views";
export type { ShellEnvModifier, ShellEnvContext } from "../../main/shell-session/shell-env-modifier/shell-env-modifier-registration"; export type { ShellEnvModifier, ShellEnvContext } from "../../main/shell-session/shell-env-modifier/shell-env-modifier-registration";
export type { ProtocolHandlerRegistration, RouteParams as ProtocolRouteParams, RouteHandler as ProtocolRouteHandler } from "../registries/protocol-handler";
export type { CommandRegistration, CommandContext } from "../../renderer/components/command-palette/registered-commands/commands";
export type { EntitySettingRegistration, EntitySettingViewProps, EntitySettingComponents } from "../registries/entity-setting-registry";
export type { WorkloadsOverviewDetailRegistration, WorkloadsOverviewDetailComponents } from "../registries/workloads-overview-detail-registry";
export type { TopBarRegistration, TopBarComponents } from "../../renderer/components/layout/top-bar/top-bar-registration";
export type { WelcomeBannerRegistration } from "../../renderer/components/+welcome/welcome-banner-items/welcome-banner-registration";
export type { WelcomeMenuRegistration } from "../../renderer/components/+welcome/welcome-menu-items/welcome-menu-registration";
export type { TrayMenuRegistration } from "../../main/tray/tray-menu-registration";

View File

@ -4,3 +4,4 @@
*/ */
export { ExtensionStore } from "../extension-store"; export { ExtensionStore } from "../extension-store";
export type { BaseStoreParams } from "../../common/base-store";

View File

@ -6,5 +6,15 @@
export type IpcMainInvokeEvent = Electron.IpcMainInvokeEvent; export type IpcMainInvokeEvent = Electron.IpcMainInvokeEvent;
export type IpcRendererEvent = Electron.IpcRendererEvent; export type IpcRendererEvent = Electron.IpcRendererEvent;
export type IpcMainEvent = Electron.IpcMainEvent; export type IpcMainEvent = Electron.IpcMainEvent;
export type { LensExtension, LensExtensionManifest, LensExtensionId } from "../lens-extension";
export type { InstalledExtension } from "../extension-discovery/extension-discovery";
export type { Disposer } from "../../common/utils";
export {
ItemStore,
} from "../../common/item.store";
export type {
ItemObject,
} from "../../common/item.store";
export * from "./registrations"; export * from "./registrations";

View File

@ -0,0 +1,199 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
/**
* This file is for the common exports to both `Renderer.K8sApi` and `Main.K8sApi`
*
* It would be nicer if we exported this from `Common.K8sApi` but there doesn't seem
* to be a good way to deprecate an export so that will have to wait.
*/
export {
ResourceStack,
} from "../common/k8s/resource-stack";
export {
KubeObjectStore,
} from "../common/k8s-api/kube-object.store";
export {
forCluster,
forRemoteCluster,
KubeApi,
} from "../common/k8s-api/kube-api";
export type {
BaseKubeApiOptions,
DeleteResourceDescriptor,
KubeApiListOptions,
KubeApiPatchType,
KubeApiWatchCallback,
KubeApiWatchOptions,
PartialKubeObject,
PropagationPolicy,
ResourceDescriptor,
} from "../common/k8s-api/kube-api";
export type {
IKubeWatchEvent,
} from "../common/k8s-api/kube-watch-event";
export {
KubeObject,
KubeStatus,
} from "../common/k8s-api/kube-object";
export type {
KubeStatusData,
} from "../common/k8s-api/kube-object";
export {
ClusterRole,
ClusterRoleApi,
ClusterRoleBinding,
ClusterRoleBindingApi,
ConfigMap,
ConfigMapApi,
CronJob,
CronJobApi,
CustomResourceDefinition,
CustomResourceDefinitionApi,
DaemonSet,
DaemonSetApi,
Deployment,
DeploymentApi,
Endpoint,
EndpointApi,
HorizontalPodAutoscaler,
HorizontalPodAutoscalerApi,
Ingress,
IngressApi,
Job,
JobApi,
KubeEvent,
KubeEventApi,
LimitRange,
LimitRangeApi,
Namespace,
NamespaceApi,
NetworkPolicy,
NetworkPolicyApi,
Node,
NodesApi,
PersistentVolume,
PersistentVolumeApi,
PersistentVolumeClaim,
PersistentVolumeClaimsApi,
Pod,
PodDisruptionBudget,
PodDisruptionBudgetApi,
PodsApi,
ReplicaSet,
ReplicaSetApi,
ResourceQuota,
ResourceQuotaApi,
Role,
RoleApi,
RoleBinding,
RoleBindingApi,
Secret,
SecretApi,
SecretType,
Service,
ServiceAccount,
ServiceAccountApi,
ServiceApi,
StatefulSet,
StatefulSetApi,
StorageClass,
StorageClassApi,
} from "../common/k8s-api/endpoints";
export {
KubeObjectStatusLevel,
} from "./registries/kube-object-status-registry";
export type {
IKubeApiCluster,
IKubeApiOptions,
IKubeApiQueryParams,
ILocalKubeApiConfig,
IRemoteKubeApiConfig,
} from "../common/k8s-api/kube-api";
export type {
KubeObjectConstructor,
KubeObjectMetadata,
LabelMatchExpression,
LabelSelector,
} from "../common/k8s-api/kube-object";
export type {
AdditionalPrinterColumnsCommon,
AdditionalPrinterColumnsV1,
AdditionalPrinterColumnsV1Beta,
ClusterRoleBindingSubject,
ClusterRoleBindingSubjectKind,
ContainerProbe,
ContainerState,
ContainerStateRunning,
ContainerStateTerminated,
ContainerStateWaiting,
CRDVersion,
CustomResourceDefinitionSpec,
CustomResourceDefinitionStatus,
EndpointAddress,
EndpointSubset,
HpaMetricType,
IContainerProbe,
IEndpointAddress,
IEndpointPort,
IEndpointSubset,
IExtensionsBackend,
IHpaMetric,
IHpaMetricData,
IIngressBackend,
IIngressService,
ILoadBalancerIngress,
INetworkingBackend,
IPodContainer,
IPodContainerStatus,
IPodLogsQuery,
IPolicyEgress,
IPolicyIngress,
IPolicyIpBlock,
IResourceQuotaValues,
ISecretRef,
ITargetRef,
LimitRangeItem,
NetworkPolicyPeer,
NetworkPolicyPort,
NetworkPolicySpec,
NodeCondition,
NodeTaint,
PodMetrics,
PodStatus,
PolicyType,
RoleBindingSubject,
RoleBindingSubjectKind,
SecretData,
ServicePort,
} from "../common/k8s-api/endpoints";
export type {
Affinity,
IAffinity,
IMatchExpression,
INodeAffinity,
IPodAffinity,
IToleration,
} from "../common/k8s-api/workload-kube-object";
export type {
KubeObjectStatus,
} from "./registries/kube-object-status-registry";
export type {
JsonApi,
JsonApiConfig,
JsonApiData,
JsonApiError,
JsonApiErrorParsed,
JsonApiLog,
JsonApiParams,
} from "../common/k8s-api/json-api";
export type {
KubeJsonApi,
KubeJsonApiData,
KubeJsonApiDataList,
KubeJsonApiListMetadata,
KubeJsonApiMetadata,
} from "../common/k8s-api/kube-json-api";

View File

@ -14,18 +14,45 @@ import {
setLensExtensionDependencies, setLensExtensionDependencies,
} from "./lens-extension-set-dependencies"; } from "./lens-extension-set-dependencies";
export type LensExtensionId = string; // path to manifest (package.json) /**
* A named type for when functions should expect an extension's ID
*/
export type LensExtensionId = string;
export type LensExtensionConstructor = new (...args: ConstructorParameters<typeof LensExtension>) => LensExtension; export type LensExtensionConstructor = new (...args: ConstructorParameters<typeof LensExtension>) => LensExtension;
/**
* The required fields that an extension's `package.json` must include
*/
export interface LensExtensionManifest extends PackageJson { export interface LensExtensionManifest extends PackageJson {
/**
* The name of the extension
*/
name: string; name: string;
/**
* The SemVer version string
*/
version: string; version: string;
main?: string; // path to %ext/dist/main.js
renderer?: string; // path to %ext/dist/renderer.js /**
* The path to compiled JS file for the main side of the extension.
*/
main?: string;
/**
* The path to compiled JS file for the renderer side of the extension.
*/
renderer?: string;
} }
/**
* @internal
*/
export const Disposers = Symbol(); export const Disposers = Symbol();
/**
* The base class for all extensions.
*/
export class LensExtension { export class LensExtension {
readonly id: LensExtensionId; readonly id: LensExtensionId;
readonly manifest: LensExtensionManifest; readonly manifest: LensExtensionManifest;
@ -40,6 +67,9 @@ export class LensExtension {
return this._isEnabled; return this._isEnabled;
} }
/**
* @internal
*/
[Disposers] = disposer(); [Disposers] = disposer();
constructor({ id, manifest, manifestPath, isBundled }: InstalledExtension) { constructor({ id, manifest, manifestPath, isBundled }: InstalledExtension) {
@ -64,6 +94,9 @@ export class LensExtension {
private dependencies: LensExtensionDependencies; private dependencies: LensExtensionDependencies;
/**
* @internal
*/
[setLensExtensionDependencies] = (dependencies: LensExtensionDependencies) => { [setLensExtensionDependencies] = (dependencies: LensExtensionDependencies) => {
this.dependencies = dependencies; this.dependencies = dependencies;
}; };

View File

@ -3,6 +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.
*/ */
export * from "../common-k8s-api";
/** /**
* @deprecated This function never works * @deprecated This function never works
* @returns false * @returns false
@ -10,45 +12,3 @@
export function isAllowedResource(...args: any[]) { export function isAllowedResource(...args: any[]) {
return Boolean(void args); return Boolean(void args);
} }
export { ResourceStack } from "../../common/k8s/resource-stack";
export { apiManager } from "../../common/k8s-api/api-manager";
export { KubeApi, forCluster, forRemoteCluster } from "../../common/k8s-api/kube-api";
export { KubeObject, KubeStatus } from "../../common/k8s-api/kube-object";
export { KubeObjectStore } from "../../common/k8s-api/kube-object.store";
export { Pod, podsApi, PodsApi } from "../../common/k8s-api/endpoints/pods.api";
export { Node, nodesApi, NodesApi } from "../../common/k8s-api/endpoints/nodes.api";
export { Deployment, deploymentApi, DeploymentApi } from "../../common/k8s-api/endpoints/deployment.api";
export { DaemonSet, daemonSetApi } from "../../common/k8s-api/endpoints/daemon-set.api";
export { StatefulSet, statefulSetApi } from "../../common/k8s-api/endpoints/stateful-set.api";
export { Job, jobApi } from "../../common/k8s-api/endpoints/job.api";
export { CronJob, cronJobApi } from "../../common/k8s-api/endpoints/cron-job.api";
export { ConfigMap, configMapApi } from "../../common/k8s-api/endpoints/configmap.api";
export { Secret, secretsApi } from "../../common/k8s-api/endpoints/secret.api";
export { ReplicaSet, replicaSetApi } from "../../common/k8s-api/endpoints/replica-set.api";
export { ResourceQuota, resourceQuotaApi } from "../../common/k8s-api/endpoints/resource-quota.api";
export { LimitRange, limitRangeApi } from "../../common/k8s-api/endpoints/limit-range.api";
export { HorizontalPodAutoscaler, hpaApi } from "../../common/k8s-api/endpoints/hpa.api";
export { PodDisruptionBudget, pdbApi } from "../../common/k8s-api/endpoints/poddisruptionbudget.api";
export { Service, serviceApi } from "../../common/k8s-api/endpoints/service.api";
export { Endpoint, endpointApi } from "../../common/k8s-api/endpoints/endpoint.api";
export { Ingress, ingressApi, IngressApi } from "../../common/k8s-api/endpoints/ingress.api";
export { NetworkPolicy, networkPolicyApi } from "../../common/k8s-api/endpoints/network-policy.api";
export { PersistentVolume, persistentVolumeApi } from "../../common/k8s-api/endpoints/persistent-volume.api";
export { PersistentVolumeClaim, pvcApi, PersistentVolumeClaimsApi } from "../../common/k8s-api/endpoints/persistent-volume-claims.api";
export { StorageClass, storageClassApi } from "../../common/k8s-api/endpoints/storage-class.api";
export { Namespace, namespacesApi } from "../../common/k8s-api/endpoints/namespaces.api";
export { KubeEvent, eventApi } from "../../common/k8s-api/endpoints/events.api";
export { ServiceAccount, serviceAccountsApi } from "../../common/k8s-api/endpoints/service-accounts.api";
export { Role, roleApi } from "../../common/k8s-api/endpoints/role.api";
export { RoleBinding, roleBindingApi } from "../../common/k8s-api/endpoints/role-binding.api";
export { ClusterRole, clusterRoleApi } from "../../common/k8s-api/endpoints/cluster-role.api";
export { ClusterRoleBinding, clusterRoleBindingApi } from "../../common/k8s-api/endpoints/cluster-role-binding.api";
export { CustomResourceDefinition, crdApi } from "../../common/k8s-api/endpoints/crd.api";
// types
export type { ILocalKubeApiConfig, IRemoteKubeApiConfig, IKubeApiCluster } from "../../common/k8s-api/kube-api";
export type { IPodContainer, IPodContainerStatus } from "../../common/k8s-api/endpoints/pods.api";
export type { ISecretRef } from "../../common/k8s-api/endpoints/secret.api";
export type { KubeObjectMetadata, KubeStatusData } from "../../common/k8s-api/kube-object";
export type { KubeObjectStoreLoadAllParams, KubeObjectStoreLoadingParams, KubeObjectStoreSubscribeParams } from "../../common/k8s-api/kube-object.store";

View File

@ -2,7 +2,7 @@
"name": "@k8slens/extensions", "name": "@k8slens/extensions",
"productName": "OpenLens extensions", "productName": "OpenLens extensions",
"description": "OpenLens - Open Source Kubernetes IDE: extensions", "description": "OpenLens - Open Source Kubernetes IDE: extensions",
"version": "0.0.0", "version": "5.3.0",
"copyright": "© 2021 OpenLens Authors", "copyright": "© 2021 OpenLens Authors",
"license": "MIT", "license": "MIT",
"main": "dist/src/extensions/extension-api.js", "main": "dist/src/extensions/extension-api.js",

View File

@ -3,9 +3,21 @@
* 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 { KubeObject, KubeObjectStatus } from "../renderer-api/k8s-api"; import type { KubeObject } from "../renderer-api/k8s-api";
import { BaseRegistry } from "./base-registry"; import { BaseRegistry } from "./base-registry";
export enum KubeObjectStatusLevel {
INFO = 1,
WARNING = 2,
CRITICAL = 3,
}
export interface KubeObjectStatus {
level: KubeObjectStatusLevel;
text: string;
timestamp?: string;
}
export interface KubeObjectStatusRegistration { export interface KubeObjectStatusRegistration {
kind: string; kind: string;
apiVersions: string[]; apiVersions: string[];

View File

@ -8,7 +8,7 @@ import type React from "react";
import { BaseRegistry } from "./base-registry"; import { BaseRegistry } from "./base-registry";
export interface WorkloadsOverviewDetailComponents { export interface WorkloadsOverviewDetailComponents {
Details: React.ComponentType<{}>; Details: React.ComponentType;
} }
export interface WorkloadsOverviewDetailRegistration { export interface WorkloadsOverviewDetailRegistration {

View File

@ -8,9 +8,19 @@ import type { CatalogCategory, CatalogEntity } from "../../common/catalog";
import { catalogEntityRegistry as registry } from "../../renderer/api/catalog-entity-registry"; import { catalogEntityRegistry as registry } from "../../renderer/api/catalog-entity-registry";
import type { CatalogEntityOnBeforeRun } from "../../renderer/api/catalog-entity-registry"; import type { CatalogEntityOnBeforeRun } from "../../renderer/api/catalog-entity-registry";
import type { Disposer } from "../../common/utils"; import type { Disposer } from "../../common/utils";
export type {
EntityFilter,
CatalogEntityOnBeforeRun,
} from "../../renderer/api/catalog-entity-registry";
export type { CatalogCategoryRegistry } from "../../common/catalog/catalog-category-registry";
export { catalogCategoryRegistry as catalogCategories } from "../../common/catalog/catalog-category-registry"; export { catalogCategoryRegistry as catalogCategories } from "../../common/catalog/catalog-category-registry";
export class CatalogEntityRegistry { /**
* The registry for entities synced to renderer
*/
class CatalogEntityRegistry {
/** /**
* Currently active/visible entity * Currently active/visible entity
*/ */
@ -18,18 +28,36 @@ export class CatalogEntityRegistry {
return registry.activeEntity; return registry.activeEntity;
} }
/**
* The mapping of all entities from ID to instance
*/
get entities(): Map<string, CatalogEntity> { get entities(): Map<string, CatalogEntity> {
return registry.entities; return registry.entities;
} }
getById(id: string) { /**
* Attempt to get a catalog entity by its ID.
* @param id The ID of the desired entity
*/
getById(id: string): CatalogEntity | undefined {
return this.entities.get(id); return this.entities.get(id);
} }
/**
* Get all the entities of a specific version and kind
* @param apiVersion The version string of an entity
* @param kind The kind of the entity
* @returns A list of entities matching that `apiVersion` and `kind`
*/
getItemsForApiKind<T extends CatalogEntity>(apiVersion: string, kind: string): T[] { getItemsForApiKind<T extends CatalogEntity>(apiVersion: string, kind: string): T[] {
return registry.getItemsForApiKind<T>(apiVersion, kind); return registry.getItemsForApiKind<T>(apiVersion, kind);
} }
/**
* Get all the entities for the kinds declared by a specific category
* @param category The category that declares different apiVersions for a specific kind
* @returns A list of entities matching the deckared `apiVersion`'s and `kind`
*/
getItemsForCategory<T extends CatalogEntity>(category: CatalogCategory): T[] { getItemsForCategory<T extends CatalogEntity>(category: CatalogCategory): T[] {
return registry.getItemsForCategory(category); return registry.getItemsForCategory(category);
} }
@ -47,4 +75,6 @@ export class CatalogEntityRegistry {
} }
} }
export type { CatalogEntityRegistry };
export const catalogEntities = new CatalogEntityRegistry(); export const catalogEntities = new CatalogEntityRegistry();

View File

@ -5,16 +5,26 @@
import { asLegacyGlobalFunctionForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api"; import { asLegacyGlobalFunctionForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-function-for-extension-api";
import createTerminalTabInjectable from "../../renderer/components/dock/terminal/create-terminal-tab.injectable"; import createTerminalTabInjectable from "../../renderer/components/dock/terminal/create-terminal-tab.injectable";
import terminalStoreInjectable from "../../renderer/components/dock/terminal/store.injectable"; import terminalStoreInjectable from "../../renderer/components/dock/terminal/store.injectable";
import type { TerminalStore as TerminalStoreType, TerminalTab } from "../../renderer/components/dock/terminal/store";
import { asLegacyGlobalObjectForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api"; import { asLegacyGlobalObjectForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
import logTabStoreInjectable from "../../renderer/components/dock/logs/tab-store.injectable"; import logTabStoreInjectable from "../../renderer/components/dock/logs/tab-store.injectable";
import commandOverlayInjectable from "../../renderer/components/command-palette/command-overlay.injectable"; import commandOverlayInjectable from "../../renderer/components/command-palette/command-overlay.injectable";
import { asLegacyGlobalObjectForExtensionApiWithModifications } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api-with-modifications"; import type { CommandOverlay as CommandPalletState } from "../../renderer/components/command-palette/command-overlay.injectable";
import createPodLogsTabInjectable from "../../renderer/components/dock/logs/create-pod-logs-tab.injectable"; import createPodLogsTabInjectable, { PodLogsTabData } from "../../renderer/components/dock/logs/create-pod-logs-tab.injectable";
import createWorkloadLogsTabInjectable from "../../renderer/components/dock/logs/create-workload-logs-tab.injectable"; import createWorkloadLogsTabInjectable, { WorkloadLogsTabData } from "../../renderer/components/dock/logs/create-workload-logs-tab.injectable";
import sendCommandInjectable from "../../renderer/components/dock/terminal/send-command.injectable"; import sendCommandInjectable, { SendCommandOptions } from "../../renderer/components/dock/terminal/send-command.injectable";
import { podsStore } from "../../renderer/components/+workloads-pods/pods.store"; import { podsStore } from "../../renderer/components/+workloads-pods/pods.store";
import renameTabInjectable from "../../renderer/components/dock/dock/rename-tab.injectable"; import renameTabInjectable from "../../renderer/components/dock/dock/rename-tab.injectable";
import type { DockTabStorageState } from "../../renderer/components/dock/dock-tab-store/dock-tab.store";
import type { LogTabData, LogTabOwnerRef, LogTabStore } from "../../renderer/components/dock/logs/tab-store";
import type { CommandActionContext, CommandActionNavigateOptions } from "../../renderer/components/command-palette/registered-commands/commands";
import type { TerminalApi, TerminalApiQuery, TerminalChannels, TerminalEvents, TerminalMessage } from "../../renderer/api/terminal-api";
import type { Terminal } from "../../renderer/components/dock/terminal/terminal";
import type { WebSocketApiState } from "../../renderer/api/websocket-api";
import type { HeaderCustomizer, ItemsFilters, ItemsFilter, SearchFilter, SearchFilters, HeaderPlaceholders, ItemListLayout, ItemListLayoutProps } from "../../renderer/components/item-object-list";
import type { ItemListLayoutHeader, ItemListLayoutHeaderProps } from "../../renderer/components/item-object-list/header";
import type { Filter, FilterType } from "../../renderer/components/item-object-list/page-filters.store";
// layouts // layouts
export * from "../../renderer/components/layout/main-layout"; export * from "../../renderer/components/layout/main-layout";
@ -29,15 +39,37 @@ export * from "../../renderer/components/checkbox";
export * from "../../renderer/components/radio"; export * from "../../renderer/components/radio";
export * from "../../renderer/components/select"; export * from "../../renderer/components/select";
export * from "../../renderer/components/slider"; export * from "../../renderer/components/slider";
export * from "../../renderer/components/switch"; export { FormSwitch, Switcher } from "../../renderer/components/switch";
export * from "../../renderer/components/input/input"; export type { SwitcherProps, SwitcherStyles } from "../../renderer/components/switch";
export {
Input,
InputValidators,
SearchInput,
} from "../../renderer/components/input";
export type {
IconData,
IconDataFnArg,
InputElement,
InputElementProps,
InputProps,
InputState,
InputValidator,
SearchInputProps,
SearchInputUrlProps,
} from "../../renderer/components/input";
// command-overlay // command-overlay
export const CommandOverlay = asLegacyGlobalObjectForExtensionApi(commandOverlayInjectable); export type {
CommandPalletState,
CommandActionContext,
CommandActionNavigateOptions,
};
export const CommandOverlay = asLegacyGlobalObjectForExtensionApi(commandOverlayInjectable) as CommandPalletState;
export type { export type {
CategoryColumnRegistration, CategoryColumnRegistration,
AdditionalCategoryColumnRegistration, AdditionalCategoryColumnRegistration,
TitleCellProps,
} from "../../renderer/components/+catalog/custom-category-columns"; } from "../../renderer/components/+catalog/custom-category-columns";
// other components // other components
@ -59,14 +91,32 @@ export * from "../../renderer/components/+workloads-pods/pod-details-list";
export * from "../../renderer/components/+namespaces/namespace-select"; export * from "../../renderer/components/+namespaces/namespace-select";
export * from "../../renderer/components/+namespaces/namespace-select-filter"; export * from "../../renderer/components/+namespaces/namespace-select-filter";
export * from "../../renderer/components/layout/sub-title"; export * from "../../renderer/components/layout/sub-title";
export * from "../../renderer/components/input/search-input"; export * from "../../renderer/components/chart";
export * from "../../renderer/components/chart/bar-chart";
export * from "../../renderer/components/chart/pie-chart";
// kube helpers // kube helpers
export * from "../../renderer/components/kube-detail-params"; export * from "../../renderer/components/kube-detail-params";
export * from "../../renderer/components/kube-object-details"; export * from "../../renderer/components/kube-object-details";
export * from "../../renderer/components/kube-object-list-layout"; export * from "../../renderer/components/kube-object-list-layout";
export type { AddRemoveButtonsProps } from "../../renderer/components/add-remove-buttons";
export {
cssNames,
type IClassName,
type IClassNameMap,
} from "../../renderer/utils";
export type {
HeaderCustomizer,
ItemsFilters,
ItemsFilter,
FilterType,
Filter,
SearchFilter,
SearchFilters,
HeaderPlaceholders,
ItemListLayout,
ItemListLayoutProps,
ItemListLayoutHeader,
ItemListLayoutHeaderProps,
};
export * from "../../renderer/components/kube-object-menu"; export * from "../../renderer/components/kube-object-menu";
export * from "../../renderer/components/kube-object-meta"; export * from "../../renderer/components/kube-object-meta";
export * from "../../renderer/components/+events/kube-event-details"; export * from "../../renderer/components/+events/kube-event-details";
@ -74,31 +124,59 @@ export * from "../../renderer/components/+events/kube-event-details";
// specific exports // specific exports
export * from "../../renderer/components/status-brick"; export * from "../../renderer/components/status-brick";
export type {
SendCommandOptions,
PodLogsTabData,
WorkloadLogsTabData,
DockTabStorageState,
};
export type {
TabKind,
TabId,
DockTabCreateOption,
BaseDockTabCreateOptions,
} from "../../renderer/components/dock/dock/store";
export const createTerminalTab = asLegacyGlobalFunctionForExtensionApi(createTerminalTabInjectable); export const createTerminalTab = asLegacyGlobalFunctionForExtensionApi(createTerminalTabInjectable);
export const terminalStore = asLegacyGlobalObjectForExtensionApiWithModifications(terminalStoreInjectable, {
sendCommand: () => asLegacyGlobalFunctionForExtensionApi(sendCommandInjectable), export type {
TerminalStoreType,
TerminalApi,
Terminal,
TerminalTab,
TerminalApiQuery,
WebSocketApiState,
TerminalEvents,
TerminalMessage,
TerminalChannels,
};
export const terminalStore = Object.assign(asLegacyGlobalObjectForExtensionApi(terminalStoreInjectable), {
sendCommand: asLegacyGlobalFunctionForExtensionApi(sendCommandInjectable),
}); });
export const logTabStore = asLegacyGlobalObjectForExtensionApiWithModifications(logTabStoreInjectable, {
createPodTab: () => asLegacyGlobalFunctionForExtensionApi(createPodLogsTabInjectable), export const TerminalStore = {
createWorkloadTab: () => asLegacyGlobalFunctionForExtensionApi(createWorkloadLogsTabInjectable), getInstance() {
renameTab: () => (tabId: string): void => { return terminalStore;
},
createInstance() {
return terminalStore;
},
resetInstance() {
console.warn("TerminalStore.resetInstance() does nothing");
},
};
export type { LogTabStore, LogTabData, LogTabOwnerRef };
export const logTabStore = Object.assign(asLegacyGlobalObjectForExtensionApi(logTabStoreInjectable), {
createPodTab: asLegacyGlobalFunctionForExtensionApi(createPodLogsTabInjectable),
createWorkloadTab: asLegacyGlobalFunctionForExtensionApi(createWorkloadLogsTabInjectable),
renameTab: (tabId: string): void => {
const renameTab = asLegacyGlobalFunctionForExtensionApi(renameTabInjectable); const renameTab = asLegacyGlobalFunctionForExtensionApi(renameTabInjectable);
const tabData = logTabStore.getData(tabId); const tabData = logTabStore.getData(tabId);
const pod = podsStore.getById(tabData.selectedPodId); const pod = podsStore.getById(tabData.selectedPodId);
renameTab(tabId, `Pod ${pod.getName()}`); renameTab(tabId, `Pod ${pod.getName()}`);
}, },
tabs: () => undefined, tabs: undefined,
}); });
export class TerminalStore {
static getInstance() {
return terminalStore;
}
static createInstance() {
return terminalStore;
}
static resetInstance() {
console.warn("TerminalStore.resetInstance() does nothing");
}
}

View File

@ -12,80 +12,88 @@ export function isAllowedResource(resource: KubeResource | KubeResource[]) {
const resources = castArray(resource); const resources = castArray(resource);
return resources.every(x => _isAllowedResource(x)); return resources.every(_isAllowedResource);
} }
export { ResourceStack } from "../../common/k8s/resource-stack"; export * from "../common-k8s-api";
export { apiManager } from "../../common/k8s-api/api-manager";
export { KubeObjectStore } from "../../common/k8s-api/kube-object.store";
export { KubeApi, forCluster, forRemoteCluster } from "../../common/k8s-api/kube-api";
export { KubeObject, KubeStatus } from "../../common/k8s-api/kube-object";
export { Pod, podsApi, PodsApi } from "../../common/k8s-api/endpoints";
export { Node, nodesApi, NodesApi } from "../../common/k8s-api/endpoints";
export { Deployment, deploymentApi, DeploymentApi } from "../../common/k8s-api/endpoints";
export { DaemonSet, daemonSetApi } from "../../common/k8s-api/endpoints";
export { StatefulSet, statefulSetApi } from "../../common/k8s-api/endpoints";
export { Job, jobApi } from "../../common/k8s-api/endpoints";
export { CronJob, cronJobApi } from "../../common/k8s-api/endpoints";
export { ConfigMap, configMapApi } from "../../common/k8s-api/endpoints";
export { Secret, secretsApi } from "../../common/k8s-api/endpoints";
export { ReplicaSet, replicaSetApi } from "../../common/k8s-api/endpoints";
export { ResourceQuota, resourceQuotaApi } from "../../common/k8s-api/endpoints";
export { LimitRange, limitRangeApi } from "../../common/k8s-api/endpoints";
export { HorizontalPodAutoscaler, hpaApi } from "../../common/k8s-api/endpoints";
export { PodDisruptionBudget, pdbApi } from "../../common/k8s-api/endpoints";
export { Service, serviceApi } from "../../common/k8s-api/endpoints";
export { Endpoint, endpointApi } from "../../common/k8s-api/endpoints";
export { Ingress, ingressApi, IngressApi } from "../../common/k8s-api/endpoints";
export { NetworkPolicy, networkPolicyApi } from "../../common/k8s-api/endpoints";
export { PersistentVolume, persistentVolumeApi } from "../../common/k8s-api/endpoints";
export { PersistentVolumeClaim, pvcApi, PersistentVolumeClaimsApi } from "../../common/k8s-api/endpoints";
export { StorageClass, storageClassApi } from "../../common/k8s-api/endpoints";
export { Namespace, namespacesApi } from "../../common/k8s-api/endpoints";
export { KubeEvent, eventApi } from "../../common/k8s-api/endpoints";
export { ServiceAccount, serviceAccountsApi } from "../../common/k8s-api/endpoints";
export { Role, roleApi } from "../../common/k8s-api/endpoints";
export { RoleBinding, roleBindingApi } from "../../common/k8s-api/endpoints";
export { ClusterRole, clusterRoleApi } from "../../common/k8s-api/endpoints";
export { ClusterRoleBinding, clusterRoleBindingApi } from "../../common/k8s-api/endpoints";
export { CustomResourceDefinition, crdApi } from "../../common/k8s-api/endpoints";
export { KubeObjectStatusLevel } from "./kube-object-status";
export { KubeJsonApi } from "../../common/k8s-api/kube-json-api";
// types export type {
export type { ILocalKubeApiConfig, IRemoteKubeApiConfig, IKubeApiCluster } from "../../common/k8s-api/kube-api"; KubeResource,
export type { IPodContainer, IPodContainerStatus } from "../../common/k8s-api/endpoints"; } from "../../common/rbac";
export type { ISecretRef } from "../../common/k8s-api/endpoints"; export type {
export type { KubeObjectStatus } from "./kube-object-status"; IKubeObjectRef,
export type { KubeObjectMetadata, KubeStatusData } from "../../common/k8s-api/kube-object"; } from "../../common/k8s-api/kube-api-parse";
export type { KubeObjectStoreLoadAllParams, KubeObjectStoreLoadingParams, KubeObjectStoreSubscribeParams } from "../../common/k8s-api/kube-object.store"; export {
apiManager,
} from "../../common/k8s-api/api-manager";
export type {
ApiManager,
} from "../../common/k8s-api/api-manager";
export {
clusterRoleApi,
clusterRoleBindingApi,
configMapApi,
crdApi,
cronJobApi,
daemonSetApi,
deploymentApi,
endpointApi,
eventApi,
hpaApi,
ingressApi,
jobApi,
limitRangeApi,
namespacesApi,
networkPolicyApi,
nodesApi,
pdbApi,
persistentVolumeApi,
podsApi,
pvcApi,
replicaSetApi,
resourceQuotaApi,
roleApi,
roleBindingApi,
secretsApi,
serviceAccountsApi,
serviceApi,
statefulSetApi,
storageClassApi,
} from "../../common/k8s-api/endpoints";
// stores // stores
export type { EventStore } from "../../renderer/components/+events/event.store"; export type { ClusterRoleBindingsStore } from "../../renderer/components/+user-management/+cluster-role-bindings/store";
export type { PodsStore } from "../../renderer/components/+workloads-pods/pods.store"; export type { ClusterRolesStore } from "../../renderer/components/+user-management/+cluster-roles/store";
export type { NodesStore } from "../../renderer/components/+nodes/nodes.store";
export type { DeploymentStore } from "../../renderer/components/+workloads-deployments/deployments.store";
export type { DaemonSetStore } from "../../renderer/components/+workloads-daemonsets/daemonsets.store";
export type { StatefulSetStore } from "../../renderer/components/+workloads-statefulsets/statefulset.store";
export type { JobStore } from "../../renderer/components/+workloads-jobs/job.store";
export type { CronJobStore } from "../../renderer/components/+workloads-cronjobs/cronjob.store";
export type { ConfigMapsStore } from "../../renderer/components/+config-maps/config-maps.store"; export type { ConfigMapsStore } from "../../renderer/components/+config-maps/config-maps.store";
export type { SecretsStore } from "../../renderer/components/+config-secrets/secrets.store"; export type { CRDResourceStore } from "../../renderer/components/+custom-resources/crd-resource.store";
export type { CRDStore } from "../../renderer/components/+custom-resources/crd.store";
export type { CronJobStore } from "../../renderer/components/+workloads-cronjobs/cronjob.store";
export type { DaemonSetStore } from "../../renderer/components/+workloads-daemonsets/daemonsets.store";
export type { DeploymentStore } from "../../renderer/components/+workloads-deployments/deployments.store";
export type { EndpointStore } from "../../renderer/components/+network-endpoints/endpoints.store";
export type { EventStore } from "../../renderer/components/+events/event.store";
export type { HPAStore } from "../../renderer/components/+config-autoscalers/hpa.store";
export type { IngressStore } from "../../renderer/components/+network-ingresses/ingress.store";
export type { JobStore } from "../../renderer/components/+workloads-jobs/job.store";
export type { LimitRangesStore } from "../../renderer/components/+config-limit-ranges/limit-ranges.store";
export type { NamespaceStore } from "../../renderer/components/+namespaces/namespace-store/namespace.store";
export type { NetworkPolicyStore } from "../../renderer/components/+network-policies/network-policy.store";
export type { NodesStore } from "../../renderer/components/+nodes/nodes.store";
export type { PersistentVolumesStore } from "../../renderer/components/+storage-volumes/volumes.store";
export type { PodDisruptionBudgetsStore } from "../../renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets.store";
export type { PodsStore } from "../../renderer/components/+workloads-pods/pods.store";
export type { ReplicaSetStore } from "../../renderer/components/+workloads-replicasets/replicasets.store"; export type { ReplicaSetStore } from "../../renderer/components/+workloads-replicasets/replicasets.store";
export type { ResourceQuotasStore } from "../../renderer/components/+config-resource-quotas/resource-quotas.store"; export type { ResourceQuotasStore } from "../../renderer/components/+config-resource-quotas/resource-quotas.store";
export type { LimitRangesStore } from "../../renderer/components/+config-limit-ranges/limit-ranges.store";
export type { HPAStore } from "../../renderer/components/+config-autoscalers/hpa.store";
export type { PodDisruptionBudgetsStore } from "../../renderer/components/+config-pod-disruption-budgets/pod-disruption-budgets.store";
export type { ServiceStore } from "../../renderer/components/+network-services/services.store";
export type { EndpointStore } from "../../renderer/components/+network-endpoints/endpoints.store";
export type { IngressStore } from "../../renderer/components/+network-ingresses/ingress.store";
export type { NetworkPolicyStore } from "../../renderer/components/+network-policies/network-policy.store";
export type { PersistentVolumesStore } from "../../renderer/components/+storage-volumes/volumes.store";
export type { VolumeClaimStore } from "../../renderer/components/+storage-volume-claims/volume-claim.store";
export type { StorageClassStore } from "../../renderer/components/+storage-classes/storage-class.store";
export type { NamespaceStore } from "../../renderer/components/+namespaces/namespace-store/namespace.store";
export type { ServiceAccountsStore } from "../../renderer/components/+user-management/+service-accounts/store";
export type { RolesStore } from "../../renderer/components/+user-management/+roles/store";
export type { RoleBindingsStore } from "../../renderer/components/+user-management/+role-bindings/store"; export type { RoleBindingsStore } from "../../renderer/components/+user-management/+role-bindings/store";
export type { CRDStore } from "../../renderer/components/+custom-resources/crd.store"; export type { RolesStore } from "../../renderer/components/+user-management/+roles/store";
export type { CRDResourceStore } from "../../renderer/components/+custom-resources/crd-resource.store"; export type { SecretsStore } from "../../renderer/components/+config-secrets/secrets.store";
export type { ServiceAccountsStore } from "../../renderer/components/+user-management/+service-accounts/store";
export type { ServiceStore } from "../../renderer/components/+network-services/services.store";
export type { StatefulSetStore } from "../../renderer/components/+workloads-statefulsets/statefulset.store";
export type { StorageClassStore } from "../../renderer/components/+storage-classes/storage-class.store";
export type { VolumeClaimStore } from "../../renderer/components/+storage-volume-claims/volume-claim.store";
export type {
KubeObjectStoreLoadAllParams,
KubeObjectStoreLoadingParams,
KubeObjectStoreSubscribeParams,
} from "../../common/k8s-api/kube-object.store";

View File

@ -1,16 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
export interface KubeObjectStatus {
level: KubeObjectStatusLevel;
text: string;
timestamp?: string;
}
export enum KubeObjectStatusLevel {
INFO = 1,
WARNING = 2,
CRITICAL = 3,
}

View File

@ -5,6 +5,9 @@
import { ThemeStore } from "../../renderer/theme.store"; import { ThemeStore } from "../../renderer/theme.store";
export type { Theme } from "../../renderer/theme.store";
export type { MonacoTheme, MonacoCustomTheme } from "../../renderer/components/monaco-editor";
export function getActiveTheme() { export function getActiveTheme() {
return ThemeStore.getInstance().activeTheme; return ThemeStore.getInstance().activeTheme;
} }

View File

@ -15,6 +15,11 @@ import { preferencesURL, extensionsURL, addClusterURL, catalogURL, welcomeURL }
import { checkForUpdates, isAutoUpdateEnabled } from "../app-updater"; import { checkForUpdates, isAutoUpdateEnabled } from "../app-updater";
import type { MenuRegistration } from "./menu-registration"; import type { MenuRegistration } from "./menu-registration";
/**
* The IDs of the menus that Lens uses.
*
* Note: `"mac"` is only valid on macOS
*/
export type MenuTopId = "mac" | "file" | "edit" | "view" | "help"; export type MenuTopId = "mac" | "file" | "edit" | "view" | "help";
interface MenuItemsOpts extends MenuItemConstructorOptions { interface MenuItemsOpts extends MenuItemConstructorOptions {

View File

@ -60,6 +60,9 @@ export interface TerminalEvents extends WebSocketEvents {
} }
export class TerminalApi extends WebSocketApi<TerminalEvents> { export class TerminalApi extends WebSocketApi<TerminalEvents> {
/**
* @internal
*/
protected size: { width: number; height: number }; protected size: { width: number; height: number };
@observable public isReady = false; @observable public isReady = false;
@ -144,6 +147,9 @@ export class TerminalApi extends WebSocketApi<TerminalEvents> {
} }
} }
/**
* @internal
*/
protected _onMessage({ data, ...evt }: MessageEvent<ArrayBuffer>): void { protected _onMessage({ data, ...evt }: MessageEvent<ArrayBuffer>): void {
try { try {
const message: TerminalMessage = deserialize(new Uint8Array(data)); const message: TerminalMessage = deserialize(new Uint8Array(data));
@ -169,6 +175,9 @@ export class TerminalApi extends WebSocketApi<TerminalEvents> {
} }
} }
/**
* @internal
*/
protected _onOpen(evt: Event) { protected _onOpen(evt: Event) {
// Client should send terminal size in special channel 4, // Client should send terminal size in special channel 4,
// But this size will be changed by terminal.fit() // But this size will be changed by terminal.fit()
@ -176,11 +185,17 @@ export class TerminalApi extends WebSocketApi<TerminalEvents> {
super._onOpen(evt); super._onOpen(evt);
} }
/**
* @internal
*/
protected _onClose(evt: CloseEvent) { protected _onClose(evt: CloseEvent) {
super._onClose(evt); super._onClose(evt);
this.isReady = false; this.isReady = false;
} }
/**
* @internal
*/
protected emitStatus(data: string, options: { color?: TerminalColor; showTime?: boolean } = {}) { protected emitStatus(data: string, options: { color?: TerminalColor; showTime?: boolean } = {}) {
const { color, showTime } = options; const { color, showTime } = options;
const time = showTime ? `${(new Date()).toLocaleString()} ` : ""; const time = showTime ? `${(new Date()).toLocaleString()} ` : "";
@ -192,6 +207,9 @@ export class TerminalApi extends WebSocketApi<TerminalEvents> {
this.emit("data", `${time}${data}\r\n`); this.emit("data", `${time}${data}\r\n`);
} }
/**
* @internal
*/
protected emitError(error: string) { protected emitError(error: string) {
this.emitStatus(error, { this.emitStatus(error, {
color: TerminalColor.RED, color: TerminalColor.RED,

View File

@ -8,6 +8,7 @@ import EventEmitter from "events";
import type TypedEventEmitter from "typed-emitter"; import type TypedEventEmitter from "typed-emitter";
import type { Arguments } from "typed-emitter"; import type { Arguments } from "typed-emitter";
import { isDevelopment } from "../../common/vars"; import { isDevelopment } from "../../common/vars";
import type { Defaulted } from "../utils";
interface WebsocketApiParams { interface WebsocketApiParams {
/** /**
@ -62,28 +63,29 @@ export interface WebSocketEvents {
close: () => void; close: () => void;
} }
type Defaulted<Params, DefaultParams extends keyof Params> = Required<Pick<Params, DefaultParams>> & Omit<Params, DefaultParams>; const defaultWebsocketApiParams = {
logging: isDevelopment,
reconnectDelay: 10,
flushOnOpen: true,
pingMessage: "PING",
};
export class WebSocketApi<Events extends WebSocketEvents> extends (EventEmitter as { new<T>(): TypedEventEmitter<T> })<Events> { export class WebSocketApi<Events extends WebSocketEvents> extends (EventEmitter as { new<T>(): TypedEventEmitter<T> })<Events> {
protected socket?: WebSocket | null; protected socket?: WebSocket | null;
protected pendingCommands: (string | ArrayBufferLike | Blob | ArrayBufferView)[] = []; protected pendingCommands: (string | ArrayBufferLike | Blob | ArrayBufferView)[] = [];
protected reconnectTimer?: any; protected reconnectTimer?: any;
protected pingTimer?: any; protected pingTimer?: any;
protected params: Defaulted<WebsocketApiParams, keyof typeof WebSocketApi["defaultParams"]>; private params: Defaulted<WebsocketApiParams, keyof typeof defaultWebsocketApiParams>;
@observable readyState = WebSocketApiState.PENDING; @observable readyState = WebSocketApiState.PENDING;
private static defaultParams = {
logging: isDevelopment,
reconnectDelay: 10,
flushOnOpen: true,
pingMessage: "PING",
};
constructor(params: WebsocketApiParams) { constructor(params: WebsocketApiParams) {
super(); super();
makeObservable(this); makeObservable(this);
this.params = Object.assign({}, WebSocketApi.defaultParams, params); this.params = {
...defaultWebsocketApiParams,
...params,
};
const { pingInterval } = this.params; const { pingInterval } = this.params;
if (pingInterval) { if (pingInterval) {

View File

@ -10,7 +10,7 @@ import { Icon } from "../icon";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { observable, makeObservable, action } from "mobx"; import { observable, makeObservable, action } from "mobx";
import { boundMethod } from "../../../common/utils"; import { boundMethod } from "../../../common/utils";
import type { CatalogCategory, CatalogEntityAddMenuContext, CatalogEntityAddMenu } from "../../api/catalog-entity"; import type { CatalogCategory, CatalogEntityAddMenu } from "../../api/catalog-entity";
import { EventEmitter } from "events"; import { EventEmitter } from "events";
import { navigate } from "../../navigation"; import { navigate } from "../../navigation";
import { catalogCategoryRegistry } from "../../api/catalog-category-registry"; import { catalogCategoryRegistry } from "../../api/catalog-category-registry";
@ -60,12 +60,11 @@ export class CatalogAddButton extends React.Component<CatalogAddButtonProps> {
updateCategoryItems = action((category: CatalogCategory) => { updateCategoryItems = action((category: CatalogCategory) => {
if (category instanceof EventEmitter) { if (category instanceof EventEmitter) {
const menuItems: CatalogEntityAddMenu[] = []; const menuItems: CatalogEntityAddMenu[] = [];
const context: CatalogEntityAddMenuContext = {
category.emit("catalogAddMenu", {
navigate: (url: string) => navigate(url), navigate: (url: string) => navigate(url),
menuItems, menuItems,
}; });
category.emit("catalogAddMenu", context);
this.menuItems.set(category.getId(), menuItems); this.menuItems.set(category.getId(), menuItems);
} }
}); });
@ -86,10 +85,13 @@ export class CatalogAddButton extends React.Component<CatalogAddButtonProps> {
@boundMethod @boundMethod
onButtonClick() { onButtonClick() {
const defaultAction = this.items.find(item => item.defaultAction)?.onClick; const defaultActions = this.items.filter(item => item.defaultAction);
const clickAction = defaultAction || (this.items.length === 1 ? this.items[0].onClick : null);
clickAction?.(); if (defaultActions.length === 1) {
defaultActions[0].onClick();
} else if (defaultActions.length === 0 && this.items.length === 1) {
this.items[0].onClick();
}
} }
get items() { get items() {

View File

@ -11,7 +11,14 @@ import type { TableCellProps } from "../table";
* These are the supported props for the title cell * These are the supported props for the title cell
*/ */
export interface TitleCellProps { export interface TitleCellProps {
/**
* An optional className entry
*/
className?: string; className?: string;
/**
* The actual title for the column
*/
title: string; title: string;
} }

View File

@ -45,6 +45,16 @@ interface Dependencies {
extensionInstallationStateStore: ExtensionInstallationStateStore; extensionInstallationStateStore: ExtensionInstallationStateStore;
} }
interface Dependencies {
userExtensions: IComputedValue<InstalledExtension[]>;
enableExtension: (id: LensExtensionId) => void;
disableExtension: (id: LensExtensionId) => void;
confirmUninstallExtension: (extension: InstalledExtension) => Promise<void>;
installFromInput: (input: string) => Promise<void>;
installFromSelectFileDialog: () => Promise<void>;
installOnDrop: (files: File[]) => Promise<void>;
}
@observer @observer
class NonInjectedExtensions extends React.Component<Dependencies> { class NonInjectedExtensions extends React.Component<Dependencies> {
@observable installPath = ""; @observable installPath = "";

View File

@ -88,13 +88,9 @@ class NonInjectedNamespaceSelect extends React.Component<NamespaceSelectProps &
} }
} }
export const NamespaceSelect = withInjectables<Dependencies, NamespaceSelectProps>( export const NamespaceSelect = withInjectables<Dependencies, NamespaceSelectProps>(NonInjectedNamespaceSelect, {
NonInjectedNamespaceSelect,
{
getProps: (di, props) => ({ getProps: (di, props) => ({
namespaceStore: di.inject(namespaceStoreInjectable), namespaceStore: di.inject(namespaceStoreInjectable),
...props, ...props,
}), }),
}, });
);

View File

@ -15,6 +15,9 @@ interface Dependencies {
export class NamespaceStore extends KubeObjectStore<Namespace> { export class NamespaceStore extends KubeObjectStore<Namespace> {
api = namespacesApi; api = namespacesApi;
/**
* @internal
*/
constructor(private dependencies: Dependencies) { constructor(private dependencies: Dependencies) {
super(); super();
makeObservable(this); makeObservable(this);

View File

@ -12,7 +12,12 @@ jest.mock("../../kube-object-meta");
describe("NetworkPolicyDetails", () => { describe("NetworkPolicyDetails", () => {
it("should render w/o errors", () => { it("should render w/o errors", () => {
const policy = new NetworkPolicy({ metadata: {} as any, spec: {}} as any); const policy = new NetworkPolicy({
metadata: {} as any,
kind: "NetworkPolicy",
apiVersion:"networking.k8s.io/v1",
spec: {},
});
const { container } = render(<NetworkPolicyDetails object={policy} />); const { container } = render(<NetworkPolicyDetails object={policy} />);
expect(container).toBeInstanceOf(HTMLElement); expect(container).toBeInstanceOf(HTMLElement);
@ -31,7 +36,12 @@ describe("NetworkPolicyDetails", () => {
}], }],
podSelector: {}, podSelector: {},
}; };
const policy = new NetworkPolicy({ metadata: {} as any, spec } as any); const policy = new NetworkPolicy({
metadata: {} as any,
kind: "NetworkPolicy",
apiVersion: "networking.k8s.io/v1",
spec,
});
const { container } = render(<NetworkPolicyDetails object={policy} />); const { container } = render(<NetworkPolicyDetails object={policy} />);
expect(await findByTestId(container, "egress-0")).toBeInstanceOf(HTMLElement); expect(await findByTestId(container, "egress-0")).toBeInstanceOf(HTMLElement);
@ -47,7 +57,12 @@ describe("NetworkPolicyDetails", () => {
}], }],
podSelector: {}, podSelector: {},
}; };
const policy = new NetworkPolicy({ metadata: {} as any, spec } as any); const policy = new NetworkPolicy({
metadata: {} as any,
kind: "NetworkPolicy",
apiVersion: "networking.k8s.io/v1",
spec,
});
const { container } = render(<NetworkPolicyDetails object={policy} />); const { container } = render(<NetworkPolicyDetails object={policy} />);
expect(container).toBeInstanceOf(HTMLElement); expect(container).toBeInstanceOf(HTMLElement);

View File

@ -21,6 +21,9 @@ interface State {
} }
export class ServiceAccountsSecret extends React.Component<ServiceAccountsSecretProps, State> { export class ServiceAccountsSecret extends React.Component<ServiceAccountsSecretProps, State> {
/**
* @internal
*/
public state: State = { public state: State = {
showToken: false, showToken: false,
}; };

View File

@ -9,7 +9,7 @@ import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store";
import { autoBind, cpuUnitsToNumber, unitsToBytes } from "../../utils"; import { autoBind, cpuUnitsToNumber, unitsToBytes } from "../../utils";
import { Pod, PodMetrics, podMetricsApi, podsApi } from "../../../common/k8s-api/endpoints"; import { Pod, PodMetrics, podMetricsApi, podsApi } from "../../../common/k8s-api/endpoints";
import { apiManager } from "../../../common/k8s-api/api-manager"; import { apiManager } from "../../../common/k8s-api/api-manager";
import type { WorkloadKubeObject } from "../../../common/k8s-api/workload-kube-object"; import type { KubeObject } from "../../../common/k8s-api/kube-object";
export class PodsStore extends KubeObjectStore<Pod> { export class PodsStore extends KubeObjectStore<Pod> {
api = podsApi; api = podsApi;
@ -31,7 +31,7 @@ export class PodsStore extends KubeObjectStore<Pod> {
} }
} }
getPodsByOwner(workload: WorkloadKubeObject): Pod[] { getPodsByOwner(workload: KubeObject): Pod[] {
if (!workload) return []; if (!workload) return [];
return this.items.filter(pod => { return this.items.filter(pod => {

View File

@ -16,8 +16,16 @@ import { ThemeStore } from "../../theme.store";
import { NoMetrics } from "../resource-metrics/no-metrics"; import { NoMetrics } from "../resource-metrics/no-metrics";
export interface BarChartProps extends ChartProps { export interface BarChartProps extends ChartProps {
/**
* The name of the chart
*/
name?: string; name?: string;
timeLabelStep?: number; // Minute labels appearance step
/**
* The step between the minute labels
* @default 10
*/
timeLabelStep?: number;
} }
const defaultProps: Partial<BarChartProps> = { const defaultProps: Partial<BarChartProps> = {

View File

@ -15,7 +15,9 @@ export interface CommandContext {
export interface CommandActionNavigateOptions { export interface CommandActionNavigateOptions {
/** /**
* If `true` then the navigate will only navigate on the root frame and not * If `true` then the navigate will only navigate on the root frame and not
* within a cluster * within a cluster's frame.
*
* If `false` then the navigation will only occur in the current frame
* @default false * @default false
*/ */
forceRootFrame?: boolean; forceRootFrame?: boolean;

View File

@ -15,7 +15,7 @@ import type { CommandContext, CommandRegistration } from "./commands";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import commandOverlayInjectable from "../command-overlay.injectable"; import commandOverlayInjectable from "../command-overlay.injectable";
import createTerminalTabInjectable from "../../dock/terminal/create-terminal-tab.injectable"; import createTerminalTabInjectable from "../../dock/terminal/create-terminal-tab.injectable";
import type { DockTabCreate } from "../../dock/dock/store"; import type { BaseDockTabCreateOptions } from "../../dock/dock/store";
export function isKubernetesClusterActive(context: CommandContext): boolean { export function isKubernetesClusterActive(context: CommandContext): boolean {
return context.entity?.kind === "KubernetesCluster"; return context.entity?.kind === "KubernetesCluster";
@ -24,7 +24,7 @@ export function isKubernetesClusterActive(context: CommandContext): boolean {
interface Dependencies { interface Dependencies {
openCommandDialog: (component: React.ReactElement) => void; openCommandDialog: (component: React.ReactElement) => void;
getEntitySettingItems: (kind: string, apiVersion: string, source?: string) => RegisteredEntitySetting[]; getEntitySettingItems: (kind: string, apiVersion: string, source?: string) => RegisteredEntitySetting[];
createTerminalTab: () => DockTabCreate; createTerminalTab: () => BaseDockTabCreateOptions;
} }
function getInternalCommands({ openCommandDialog, getEntitySettingItems, createTerminalTab }: Dependencies): CommandRegistration[] { function getInternalCommands({ openCommandDialog, getEntitySettingItems, createTerminalTab }: Dependencies): CommandRegistration[] {

View File

@ -27,13 +27,12 @@ export interface DialogProps {
animated?: boolean; animated?: boolean;
"data-testid"?: string; "data-testid"?: string;
} }
export interface DialogState {
interface DialogState {
isOpen: boolean; isOpen: boolean;
} }
@observer @observer
export class Dialog extends React.PureComponent<DialogProps, DialogState> { export class Dialog extends React.Component<DialogProps, DialogState> {
private contentElem: HTMLElement; private contentElem: HTMLElement;
ref = React.createRef<HTMLDivElement>(); ref = React.createRef<HTMLDivElement>();
@ -48,6 +47,9 @@ export class Dialog extends React.PureComponent<DialogProps, DialogState> {
pinned: false, pinned: false,
}; };
/**
* @internal
*/
public state: DialogState = { public state: DialogState = {
isOpen: this.props.isOpen, isOpen: this.props.isOpen,
}; };

View File

@ -4,7 +4,7 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import dockStoreInjectable from "../dock/store.injectable"; import dockStoreInjectable from "../dock/store.injectable";
import { DockTabCreateSpecific, TabKind } from "../dock/store"; import { DockTabCreateOption, TabKind } from "../dock/store";
const createResourceTabInjectable = getInjectable({ const createResourceTabInjectable = getInjectable({
id: "create-resource-tab", id: "create-resource-tab",
@ -12,7 +12,7 @@ const createResourceTabInjectable = getInjectable({
instantiate: (di) => { instantiate: (di) => {
const dockStore = di.inject(dockStoreInjectable); const dockStore = di.inject(dockStoreInjectable);
return (tabParams: DockTabCreateSpecific = {}) => return (tabParams: DockTabCreateOption = {}) =>
dockStore.createTab({ dockStore.createTab({
title: "Create resource", title: "Create resource",
...tabParams, ...tabParams,

View File

@ -4,7 +4,7 @@
*/ */
import { action, observable, reaction } from "mobx"; import { action, observable, reaction } from "mobx";
import { autoBind, StorageHelper, toJS } from "../../../utils"; import { autoBind, noop, StorageHelper, toJS } from "../../../utils";
import type { TabId } from "../dock/store"; import type { TabId } from "../dock/store";
export interface DockTabStoreOptions { export interface DockTabStoreOptions {
@ -19,36 +19,40 @@ interface DockTabStoreDependencies {
} }
export class DockTabStore<T> { export class DockTabStore<T> {
/**
* @internal
*/
protected storage?: StorageHelper<DockTabStorageState<T>>; protected storage?: StorageHelper<DockTabStorageState<T>>;
private data = observable.map<TabId, T>(); private data = observable.map<TabId, T>();
constructor(protected dependencies: DockTabStoreDependencies, protected options: DockTabStoreOptions) { /**
* @internal
*/
protected dependencies: DockTabStoreDependencies;
constructor(dependencies: DockTabStoreDependencies, { autoInit = true, storageKey }: DockTabStoreOptions) {
autoBind(this); autoBind(this);
this.options = { this.dependencies = dependencies;
autoInit: true,
...this.options,
};
if (this.options.autoInit) { this.init = storageKey
this.init(); ? (() => {
}
}
protected init() {
const { storageKey } = this.options;
// auto-save to local-storage
if (storageKey) {
this.storage = this.dependencies.createStorage<T>(storageKey, {}); this.storage = this.dependencies.createStorage<T>(storageKey, {});
this.storage.whenReady.then(() => { this.storage.whenReady.then(() => {
this.data.replace(this.storage.value); this.data.replace(this.storage.value);
reaction(() => this.toJSON(), data => this.storage.set(data)); reaction(() => this.toJSON(), data => this.storage.set(data));
}); });
})
: noop;
if (autoInit) {
this.init();
} }
} }
protected init: () => void;
protected finalizeDataForSave(data: T): T { protected finalizeDataForSave(data: T): T {
return data; return data;
} }

View File

@ -4,7 +4,7 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import dockStoreInjectable from "./store.injectable"; import dockStoreInjectable from "./store.injectable";
import type { DockTab, DockTabCreate } from "./store"; import type { DockTab, BaseDockTabCreateOptions } from "./store";
const createDockTabInjectable = getInjectable({ const createDockTabInjectable = getInjectable({
id: "create-dock-tab", id: "create-dock-tab",
@ -12,7 +12,7 @@ const createDockTabInjectable = getInjectable({
instantiate: (di) => { instantiate: (di) => {
const dockStore = di.inject(dockStoreInjectable); const dockStore = di.inject(dockStoreInjectable);
return (rawTabDesc: DockTabCreate, addNumber?: boolean): DockTab => return (rawTabDesc: BaseDockTabCreateOptions, addNumber?: boolean): DockTab =>
dockStore.createTab(rawTabDesc, addNumber); dockStore.createTab(rawTabDesc, addNumber);
}, },
}); });

View File

@ -24,12 +24,12 @@ export enum TabKind {
* *
* All fields are required. * All fields are required.
*/ */
export type DockTab = Required<DockTabCreate>; export type DockTab = Required<BaseDockTabCreateOptions>;
/** /**
* These are the arguments for creating a new Tab on the dock * These are the arguments for creating a new Tab on the dock
*/ */
export interface DockTabCreate { export interface BaseDockTabCreateOptions {
/** /**
* The ID of the tab for reference purposes. * The ID of the tab for reference purposes.
*/ */
@ -63,7 +63,7 @@ export interface DockTabCreate {
* That way users should get a type error if they try and specify a `kind` * That way users should get a type error if they try and specify a `kind`
* themselves. * themselves.
*/ */
export type DockTabCreateSpecific = Omit<DockTabCreate, "kind">; export type DockTabCreateOption = Omit<BaseDockTabCreateOptions, "kind">;
export interface DockStorageState { export interface DockStorageState {
height: number; height: number;
@ -288,7 +288,7 @@ export class DockStore implements DockStorageState {
} }
} }
createTab = action((rawTabDesc: DockTabCreate, addNumber = true): DockTab => { createTab = action((rawTabDesc: BaseDockTabCreateOptions, addNumber = true): DockTab => {
const { const {
id = uuid.v4(), id = uuid.v4(),
kind, kind,

View File

@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
import editResourceTabStoreInjectable from "./store.injectable"; import editResourceTabStoreInjectable from "./store.injectable";
import dockStoreInjectable from "../dock/store.injectable"; import dockStoreInjectable from "../dock/store.injectable";
import type { KubeObject } from "../../../../common/k8s-api/kube-object"; import type { KubeObject } from "../../../../common/k8s-api/kube-object";
import { DockStore, DockTabCreateSpecific, TabId, TabKind } from "../dock/store"; import { DockStore, DockTabCreateOption, TabId, TabKind } from "../dock/store";
import type { EditResourceTabStore } from "./store"; import type { EditResourceTabStore } from "./store";
import { runInAction } from "mobx"; import { runInAction } from "mobx";
@ -15,7 +15,7 @@ interface Dependencies {
editResourceStore: EditResourceTabStore; editResourceStore: EditResourceTabStore;
} }
const createEditResourceTab = ({ dockStore, editResourceStore }: Dependencies) => (object: KubeObject, tabParams: DockTabCreateSpecific = {}): TabId => { const createEditResourceTab = ({ dockStore, editResourceStore }: Dependencies) => (object: KubeObject, tabParams: DockTabCreateOption = {}): TabId => {
// use existing tab if already opened // use existing tab if already opened
const tabId = editResourceStore.getTabIdByResource(object); const tabId = editResourceStore.getTabIdByResource(object);

View File

@ -17,12 +17,12 @@ import { Notifications } from "../notifications";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import dockStoreInjectable from "./dock/store.injectable"; import dockStoreInjectable from "./dock/store.injectable";
export interface InfoPanelProps extends OptionalProps { export interface InfoPanelProps extends InfoPanelOptionalProps {
tabId: TabId; tabId: TabId;
submit?: () => Promise<ReactNode | string | void>; submit?: () => Promise<ReactNode | string | void>;
} }
export interface OptionalProps { export interface InfoPanelOptionalProps {
className?: string; className?: string;
error?: string; error?: string;
controls?: ReactNode; controls?: ReactNode;
@ -42,7 +42,7 @@ interface Dependencies {
@observer @observer
class NonInjectedInfoPanel extends Component<InfoPanelProps & Dependencies> { class NonInjectedInfoPanel extends Component<InfoPanelProps & Dependencies> {
static defaultProps: OptionalProps = { static defaultProps: InfoPanelOptionalProps = {
submitLabel: "Submit", submitLabel: "Submit",
submittingMessage: "Submitting..", submittingMessage: "Submitting..",
showButtons: true, showButtons: true,

View File

@ -7,19 +7,19 @@ import installChartTabStoreInjectable from "./store.injectable";
import type { HelmChart } from "../../../../common/k8s-api/endpoints/helm-charts.api"; import type { HelmChart } from "../../../../common/k8s-api/endpoints/helm-charts.api";
import { import {
DockTab, DockTab,
DockTabCreate, BaseDockTabCreateOptions,
DockTabCreateSpecific, DockTabCreateOption,
TabKind, TabKind,
} from "../dock/store"; } from "../dock/store";
import type { InstallChartTabStore } from "./store"; import type { InstallChartTabStore } from "./store";
import createDockTabInjectable from "../dock/create-dock-tab.injectable"; import createDockTabInjectable from "../dock/create-dock-tab.injectable";
interface Dependencies { interface Dependencies {
createDockTab: (rawTab: DockTabCreate, addNumber: boolean) => DockTab; createDockTab: (rawTab: BaseDockTabCreateOptions, addNumber: boolean) => DockTab;
installChartStore: InstallChartTabStore; installChartStore: InstallChartTabStore;
} }
const createInstallChartTab = ({ createDockTab, installChartStore }: Dependencies) => (chart: HelmChart, tabParams: DockTabCreateSpecific = {}) => { const createInstallChartTab = ({ createDockTab, installChartStore }: Dependencies) => (chart: HelmChart, tabParams: DockTabCreateOption = {}) => {
const { name, repo, version } = chart; const { name, repo, version } = chart;
const tab = createDockTab( const tab = createDockTab(

View File

@ -3,7 +3,7 @@
* 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 { DockTabCreate, DockTab, TabKind, TabId } from "../dock/store"; import { BaseDockTabCreateOptions, DockTab, TabKind, TabId } from "../dock/store";
import type { LogTabData } from "./tab-store"; import type { LogTabData } from "./tab-store";
import * as uuid from "uuid"; import * as uuid from "uuid";
import { runInAction } from "mobx"; import { runInAction } from "mobx";
@ -13,7 +13,7 @@ import setLogTabDataInjectable from "./set-log-tab-data.injectable";
export type CreateLogsTabData = Pick<LogTabData, "owner" | "selectedPodId" | "selectedContainer" | "namespace"> & Omit<Partial<LogTabData>, "owner" | "selectedPodId" | "selectedContainer" | "namespace">; export type CreateLogsTabData = Pick<LogTabData, "owner" | "selectedPodId" | "selectedContainer" | "namespace"> & Omit<Partial<LogTabData>, "owner" | "selectedPodId" | "selectedContainer" | "namespace">;
interface Dependencies { interface Dependencies {
createDockTab: (rawTabDesc: DockTabCreate, addNumber?: boolean) => DockTab; createDockTab: (rawTabDesc: BaseDockTabCreateOptions, addNumber?: boolean) => DockTab;
setLogTabData: (tabId: string, data: LogTabData) => void; setLogTabData: (tabId: string, data: LogTabData) => void;
} }

View File

@ -4,12 +4,12 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { podsStore } from "../../+workloads-pods/pods.store"; import { podsStore } from "../../+workloads-pods/pods.store";
import type { WorkloadKubeObject } from "../../../../common/k8s-api/workload-kube-object"; import type { DaemonSet, Deployment, Job, Pod, ReplicaSet, StatefulSet } from "../../../../common/k8s-api/endpoints";
import type { TabId } from "../dock/store"; import type { TabId } from "../dock/store";
import createLogsTabInjectable, { CreateLogsTabData } from "./create-logs-tab.injectable"; import createLogsTabInjectable, { CreateLogsTabData } from "./create-logs-tab.injectable";
export interface WorkloadLogsTabData { export interface WorkloadLogsTabData {
workload: WorkloadKubeObject; workload: DaemonSet | Deployment | Job | Pod | ReplicaSet | StatefulSet;
} }
interface Dependencies { interface Dependencies {

View File

@ -61,7 +61,10 @@ interface Dependencies {
} }
export class LogTabStore extends DockTabStore<LogTabData> { export class LogTabStore extends DockTabStore<LogTabData> {
constructor(protected dependencies: Dependencies) { /**
* @internal
*/
constructor(dependencies: Dependencies) {
super(dependencies, { super(dependencies, {
storageKey: "pod_logs", storageKey: "pod_logs",
}); });

View File

@ -4,7 +4,7 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import dockStoreInjectable from "../dock/store.injectable"; import dockStoreInjectable from "../dock/store.injectable";
import { DockTabCreateSpecific, TabKind } from "../dock/store"; import { DockTabCreateOption, TabKind } from "../dock/store";
const createTerminalTabInjectable = getInjectable({ const createTerminalTabInjectable = getInjectable({
id: "create-terminal-tab", id: "create-terminal-tab",
@ -12,7 +12,7 @@ const createTerminalTabInjectable = getInjectable({
instantiate: (di) => { instantiate: (di) => {
const dockStore = di.inject(dockStoreInjectable); const dockStore = di.inject(dockStoreInjectable);
return (tabParams: DockTabCreateSpecific = {}) => return (tabParams: DockTabCreateOption = {}) =>
dockStore.createTab({ dockStore.createTab({
title: `Terminal`, title: `Terminal`,
...tabParams, ...tabParams,

View File

@ -9,7 +9,7 @@ import { TerminalApi } from "../../../api/terminal-api";
import type { DockTab, TabId } from "../dock/store"; import type { DockTab, TabId } from "../dock/store";
import { WebSocketApiState } from "../../../api/websocket-api"; import { WebSocketApiState } from "../../../api/websocket-api";
export interface ITerminalTab extends DockTab { export interface TerminalTab extends DockTab {
node?: string; // activate node shell mode node?: string; // activate node shell mode
} }
@ -21,11 +21,14 @@ export class TerminalStore {
protected terminals = new Map<TabId, Terminal>(); protected terminals = new Map<TabId, Terminal>();
protected connections = observable.map<TabId, TerminalApi>(); protected connections = observable.map<TabId, TerminalApi>();
/**
* @internal
*/
constructor(private dependencies: Dependencies) { constructor(private dependencies: Dependencies) {
} }
@action @action
connect(tab: ITerminalTab) { connect(tab: TerminalTab) {
if (this.isConnected(tab.id)) { if (this.isConnected(tab.id)) {
return; return;
} }

View File

@ -6,7 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
import upgradeChartTabStoreInjectable from "./store.injectable"; import upgradeChartTabStoreInjectable from "./store.injectable";
import dockStoreInjectable from "../dock/store.injectable"; import dockStoreInjectable from "../dock/store.injectable";
import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api"; import type { HelmRelease } from "../../../../common/k8s-api/endpoints/helm-releases.api";
import { DockStore, DockTabCreateSpecific, TabId, TabKind } from "../dock/store"; import { DockStore, DockTabCreateOption, TabId, TabKind } from "../dock/store";
import type { UpgradeChartTabStore } from "./store"; import type { UpgradeChartTabStore } from "./store";
import { runInAction } from "mobx"; import { runInAction } from "mobx";
@ -15,7 +15,7 @@ interface Dependencies {
dockStore: DockStore; dockStore: DockStore;
} }
const createUpgradeChartTab = ({ upgradeChartStore, dockStore }: Dependencies) => (release: HelmRelease, tabParams: DockTabCreateSpecific = {}): TabId => { const createUpgradeChartTab = ({ upgradeChartStore, dockStore }: Dependencies) => (release: HelmRelease, tabParams: DockTabCreateOption = {}): TabId => {
const tabId = upgradeChartStore.getTabIdByRelease(release.getName()); const tabId = upgradeChartStore.getTabIdByRelease(release.getName());
if (tabId) { if (tabId) {

View File

@ -12,11 +12,11 @@ export interface DrawerParamTogglerProps {
label: string | number; label: string | number;
} }
interface State { export interface DrawerParamTogglerState {
open?: boolean; open?: boolean;
} }
export class DrawerParamToggler extends React.Component<DrawerParamTogglerProps, State> { export class DrawerParamToggler extends React.Component<DrawerParamTogglerProps, DrawerParamTogglerState> {
public state: State = {}; public state: DrawerParamTogglerState = {};
toggle = () => { toggle = () => {
this.setState({ open: !this.state.open }); this.setState({ open: !this.state.open });

View File

@ -12,9 +12,7 @@ import { cssNames, noop, StorageHelper } from "../../utils";
import { Icon } from "../icon"; import { Icon } from "../icon";
import { Animate, AnimateName } from "../animate"; import { Animate, AnimateName } from "../animate";
import { ResizeDirection, ResizeGrowthDirection, ResizeSide, ResizingAnchor } from "../resizing-anchor"; import { ResizeDirection, ResizeGrowthDirection, ResizeSide, ResizingAnchor } from "../resizing-anchor";
import drawerStorageInjectable, { import drawerStorageInjectable, { defaultDrawerWidth } from "./drawer-storage/drawer-storage.injectable";
defaultDrawerWidth,
} from "./drawer-storage/drawer-storage.injectable";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import historyInjectable from "../../navigation/history.injectable"; import historyInjectable from "../../navigation/history.injectable";
import type { History } from "history"; import type { History } from "history";
@ -47,7 +45,7 @@ const defaultProps: Partial<DrawerProps> = {
onClose: noop, onClose: noop,
}; };
interface State { export interface DrawerState {
isCopied: boolean; isCopied: boolean;
width: number; width: number;
} }
@ -64,7 +62,7 @@ interface Dependencies {
drawerStorage: StorageHelper<{ width: number }>; drawerStorage: StorageHelper<{ width: number }>;
} }
class NonInjectedDrawer extends React.Component<DrawerProps & Dependencies, State> { class NonInjectedDrawer extends React.Component<DrawerProps & Dependencies, DrawerState> {
static defaultProps = defaultProps as object; static defaultProps = defaultProps as object;
private mouseDownTarget: HTMLElement; private mouseDownTarget: HTMLElement;

View File

@ -21,6 +21,9 @@ interface State {
@observer @observer
export class ErrorBoundary extends React.Component<ErrorBoundaryProps, State> { export class ErrorBoundary extends React.Component<ErrorBoundaryProps, State> {
/**
* @internal
*/
public state: State = {}; public state: State = {};
componentDidCatch(error: Error, errorInfo: ErrorInfo) { componentDidCatch(error: Error, errorInfo: ErrorInfo) {

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