mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Make clear the seperation of extenal and internal stores and apis
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
9da08f4ac4
commit
ae21c88e8c
@ -5,11 +5,12 @@
|
|||||||
|
|
||||||
import type { KubeObjectStore } from "../kube-object.store";
|
import type { KubeObjectStore } from "../kube-object.store";
|
||||||
|
|
||||||
import { action, observable, makeObservable } from "mobx";
|
import type { IComputedValue } from "mobx";
|
||||||
import { autoBind, isDefined, iter } from "../../utils";
|
import { action, observable } from "mobx";
|
||||||
import type { KubeApi } from "../kube-api";
|
import type { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiDataFor, KubeObject, ObjectReference } from "../kube-object";
|
import type { KubeObject, ObjectReference } from "../kube-object";
|
||||||
import { parseKubeApi, createKubeApiURL } from "../kube-api-parse";
|
import { parseKubeApi, createKubeApiURL } from "../kube-api-parse";
|
||||||
|
import { chain } from "../../utils/iter";
|
||||||
|
|
||||||
export type RegisterableStore<Store> = Store extends KubeObjectStore<any, any, any>
|
export type RegisterableStore<Store> = Store extends KubeObjectStore<any, any, any>
|
||||||
? Store
|
? Store
|
||||||
@ -21,25 +22,35 @@ export type KubeObjectStoreFrom<Api> = Api extends KubeApi<infer KubeObj, infer
|
|||||||
? KubeObjectStore<KubeObj, Api, ApiData>
|
? KubeObjectStore<KubeObj, Api, ApiData>
|
||||||
: never;
|
: never;
|
||||||
|
|
||||||
|
export type FindApiCallback = (api: KubeApi<KubeObject>) => boolean;
|
||||||
|
|
||||||
|
interface Dependencies {
|
||||||
|
readonly apis: IComputedValue<KubeApi[]>;
|
||||||
|
readonly stores: IComputedValue<KubeObjectStore[]>;
|
||||||
|
}
|
||||||
|
|
||||||
export class ApiManager {
|
export class ApiManager {
|
||||||
private readonly apis = observable.map<string, KubeApi>();
|
private readonly externalApis = observable.array<KubeApi>();
|
||||||
private readonly stores = observable.map<string, KubeObjectStore>();
|
private readonly externalStores = observable.array<KubeObjectStore>();
|
||||||
|
|
||||||
constructor() {
|
constructor(private readonly dependencies: Dependencies) {}
|
||||||
makeObservable(this);
|
|
||||||
autoBind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
getApi(pathOrCallback: string | ((api: KubeApi<KubeObject>) => boolean)) {
|
getApi(pathOrCallback: string | FindApiCallback) {
|
||||||
if (typeof pathOrCallback === "string") {
|
const callback: FindApiCallback = typeof pathOrCallback === "function"
|
||||||
return this.apis.get(pathOrCallback) || this.apis.get(parseKubeApi(pathOrCallback).apiBase);
|
? pathOrCallback
|
||||||
}
|
: (() => {
|
||||||
|
const { apiBase } = parseKubeApi(pathOrCallback);
|
||||||
|
|
||||||
return iter.find(this.apis.values(), pathOrCallback ?? (() => true));
|
return api => api.apiBase === apiBase;
|
||||||
|
})();
|
||||||
|
|
||||||
|
return chain(this.dependencies.apis.get().values())
|
||||||
|
.concat(this.externalApis.values())
|
||||||
|
.find(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
getApiByKind(kind: string, apiVersion: string) {
|
getApiByKind(kind: string, apiVersion: string) {
|
||||||
return iter.find(this.apis.values(), api => api.kind === kind && api.apiVersionWithGroup === apiVersion);
|
return this.getApi(api => api.kind === kind && api.apiVersionWithGroup === apiVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerApi<Api>(api: RegisterableApi<Api>): void;
|
registerApi<Api>(api: RegisterableApi<Api>): void;
|
||||||
@ -47,45 +58,23 @@ export class ApiManager {
|
|||||||
* @deprecated Just register the `api` by itself
|
* @deprecated Just register the `api` by itself
|
||||||
*/
|
*/
|
||||||
registerApi<Api>(apiBase: string, api: RegisterableApi<Api>): void;
|
registerApi<Api>(apiBase: string, api: RegisterableApi<Api>): void;
|
||||||
registerApi<Api>(apiBaseRaw: string | RegisterableApi<Api>, apiRaw?: RegisterableApi<Api>) {
|
registerApi<Api>(...args: [RegisterableApi<Api>] | [string, RegisterableApi<Api>]) {
|
||||||
const api = typeof apiBaseRaw === "string"
|
if (args.length === 1) {
|
||||||
? apiRaw
|
this.externalApis.push(args[0]);
|
||||||
: apiBaseRaw;
|
} else {
|
||||||
|
this.externalApis.push(args[1]);
|
||||||
if (!api?.apiBase) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.apis.has(api.apiBase)) {
|
|
||||||
this.stores.forEach((store) => {
|
|
||||||
if (store.api === api) {
|
|
||||||
this.stores.set(api.apiBase, store);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.apis.set(api.apiBase, api);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected resolveApi(api: undefined | string | KubeApi): KubeApi | undefined {
|
unregisterApi(apiOrBase: string | KubeApi<KubeObject>) {
|
||||||
if (!api) {
|
if (typeof apiOrBase === "string") {
|
||||||
return undefined;
|
const api = this.externalApis.find(api => api.apiBase === apiOrBase);
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof api === "string") {
|
if (api) {
|
||||||
return this.getApi(api);
|
this.externalApis.remove(api);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
return api;
|
this.unregisterApi(apiOrBase.apiBase);
|
||||||
}
|
|
||||||
|
|
||||||
unregisterApi(api: string | KubeApi<KubeObject>) {
|
|
||||||
if (typeof api === "string") this.apis.delete(api);
|
|
||||||
else {
|
|
||||||
const apis = Array.from(this.apis.entries());
|
|
||||||
const entry = apis.find(entry => entry[1] === api);
|
|
||||||
|
|
||||||
if (entry) this.unregisterApi(entry[0]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,15 +82,11 @@ export class ApiManager {
|
|||||||
/**
|
/**
|
||||||
* @deprecated KubeObjectStore's should only every be about a single KubeApi type
|
* @deprecated KubeObjectStore's should only every be about a single KubeApi type
|
||||||
*/
|
*/
|
||||||
registerStore<KubeObj extends KubeObject>(store: KubeObjectStore<KubeObj, KubeApi<KubeObj>, KubeJsonApiDataFor<KubeObj>>, apis: KubeApi<KubeObj>[]): void;
|
registerStore<KubeObj>(store: RegisterableStore<KubeObj>, apis: KubeApi<KubeObject>[]): void;
|
||||||
|
|
||||||
@action
|
@action
|
||||||
registerStore<KubeObj extends KubeObject>(store: KubeObjectStore<KubeObj, KubeApi<KubeObj>, KubeJsonApiDataFor<KubeObj>>, apis: KubeApi<KubeObj>[] = [store.api]): void {
|
registerStore<KubeObj>(store: RegisterableStore<KubeObj>): void {
|
||||||
for (const api of apis.filter(isDefined)) {
|
this.externalStores.push(store);
|
||||||
if (api.apiBase) {
|
|
||||||
this.stores.set(api.apiBase, store as never);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getStore(api: string | undefined): KubeObjectStore | undefined;
|
getStore(api: string | undefined): KubeObjectStore | undefined;
|
||||||
@ -110,14 +95,18 @@ export class ApiManager {
|
|||||||
* @deprecated use an actual cast instead of hiding it with this unused type param
|
* @deprecated use an actual cast instead of hiding it with this unused type param
|
||||||
*/
|
*/
|
||||||
getStore<Store extends KubeObjectStore>(api: string | KubeApi): Store | undefined ;
|
getStore<Store extends KubeObjectStore>(api: string | KubeApi): Store | undefined ;
|
||||||
getStore(api: string | KubeApi | undefined): KubeObjectStore | undefined {
|
getStore(apiOrBase: string | KubeApi | undefined): KubeObjectStore | undefined {
|
||||||
const { apiBase } = this.resolveApi(api) ?? {};
|
if (!apiOrBase) {
|
||||||
|
return undefined;
|
||||||
if (apiBase) {
|
|
||||||
return this.stores.get(apiBase);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
const { apiBase } = typeof apiOrBase === "string"
|
||||||
|
? parseKubeApi(apiOrBase)
|
||||||
|
: apiOrBase;
|
||||||
|
|
||||||
|
return chain(this.dependencies.stores.get().values())
|
||||||
|
.concat(this.externalStores.values())
|
||||||
|
.find(store => store.api.apiBase === apiBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
lookupApiLink(ref: ObjectReference, parentObject?: KubeObject): string {
|
lookupApiLink(ref: ObjectReference, parentObject?: KubeObject): string {
|
||||||
@ -132,7 +121,7 @@ export class ApiManager {
|
|||||||
const api = this.getApi(api => api.kind === kind && api.apiVersionWithGroup == apiVersion);
|
const api = this.getApi(api => api.kind === kind && api.apiVersionWithGroup == apiVersion);
|
||||||
|
|
||||||
if (api) {
|
if (api) {
|
||||||
return api.getUrl({ namespace, name });
|
return api.formatUrlForNotListing({ namespace, name });
|
||||||
}
|
}
|
||||||
|
|
||||||
// lookup api by generated resource link
|
// lookup api by generated resource link
|
||||||
@ -151,7 +140,7 @@ export class ApiManager {
|
|||||||
const apiByKind = this.getApi(api => api.kind === kind);
|
const apiByKind = this.getApi(api => api.kind === kind);
|
||||||
|
|
||||||
if (apiByKind) {
|
if (apiByKind) {
|
||||||
return apiByKind.getUrl({ name, namespace });
|
return apiByKind.formatUrlForNotListing({ name, namespace });
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise generate link with default prefix
|
// otherwise generate link with default prefix
|
||||||
|
|||||||
10
src/common/k8s-api/api-manager/kube-object-store-token.ts
Normal file
10
src/common/k8s-api/api-manager/kube-object-store-token.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||||
|
import type { KubeObjectStore } from "../kube-object.store";
|
||||||
|
|
||||||
|
export const kubeObjectStoreInjectionToken = getInjectionToken<KubeObjectStore<any, any, any>>({
|
||||||
|
id: "kube-object-store-token",
|
||||||
|
});
|
||||||
@ -2,29 +2,28 @@
|
|||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||||
import type { KubeObjectStore } from "../kube-object.store";
|
|
||||||
import { ApiManager } from "./api-manager";
|
import { ApiManager } from "./api-manager";
|
||||||
|
import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx";
|
||||||
export const kubeObjectStoreInjectionToken = getInjectionToken<KubeObjectStore<any, any, any>>({
|
import { kubeObjectStoreInjectionToken } from "./kube-object-store-token";
|
||||||
id: "kube-object-store-token",
|
import { kubeApiInjectionToken } from "../kube-api/kube-api-injection-token";
|
||||||
});
|
import { computed } from "mobx";
|
||||||
|
|
||||||
const apiManagerInjectable = getInjectable({
|
const apiManagerInjectable = getInjectable({
|
||||||
id: "api-manager",
|
id: "api-manager",
|
||||||
instantiate: (di) => {
|
instantiate: (di) => {
|
||||||
const apiManager = new ApiManager();
|
const computedInjectMany = di.inject(computedInjectManyInjectable);
|
||||||
|
const storesAndApisCanBeCreated = di.inject(storesAndApisCanBeCreatedInjectionToken);
|
||||||
|
|
||||||
if (di.inject(storesAndApisCanBeCreatedInjectionToken)) {
|
return new ApiManager({
|
||||||
const stores = di.injectMany(kubeObjectStoreInjectionToken);
|
apis: storesAndApisCanBeCreated
|
||||||
|
? computedInjectMany(kubeApiInjectionToken)
|
||||||
for (const store of stores) {
|
: computed(() => []),
|
||||||
apiManager.registerStore(store);
|
stores: storesAndApisCanBeCreated
|
||||||
}
|
? computedInjectMany(kubeObjectStoreInjectionToken)
|
||||||
}
|
: computed(() => []),
|
||||||
|
});
|
||||||
return apiManager;
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user