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

chore: Fix new build errors in @k8slens/core

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2023-05-03 08:06:13 -04:00
parent 64f3a47230
commit 3a62cd4848
23 changed files with 99 additions and 118 deletions

View File

@ -7,9 +7,13 @@ import React from "react";
import type {
DragDropContextProps,
DraggableProps,
DraggableProvided,
DraggableProvidedDraggableProps,
DraggableStateSnapshot,
DroppableProps,
DroppableProvided,
DroppableProvidedProps,
DroppableStateSnapshot,
} from "react-beautiful-dnd";
export const DragDropContext = ({ children }: DragDropContextProps) => <>{ children }</>;
@ -20,14 +24,14 @@ export const Draggable = ({ children }: DraggableProps) => (
{
draggableProps: {} as DraggableProvidedDraggableProps,
innerRef: () => {},
},
} as unknown as DraggableProvided,
{
isDragging: false,
isDropAnimating: false,
},
} as DraggableStateSnapshot,
{
draggableId: "some-mock-draggable-id",
mode: "FLUID",
type: "FLUID",
source: {
droppableId: "some-mock-droppable-id",
index: 0,
@ -44,11 +48,11 @@ export const Droppable = ({ children }: DroppableProps) => (
{
droppableProps: {} as DroppableProvidedProps,
innerRef: () => {},
},
} as unknown as DroppableProvided,
{
isDraggingOver: false,
isUsingPlaceholder: false,
},
} as DroppableStateSnapshot,
)
}
</>

View File

@ -15,7 +15,7 @@ import appPathsInjectable from "./app-paths.injectable";
describe("app-paths", () => {
let builder: ApplicationBuilder;
beforeEach(() => {
beforeEach(async () => {
builder = getApplicationBuilder();
const defaultAppPathsStub: AppPaths = {

View File

@ -6,6 +6,7 @@
import { getEnvironmentSpecificLegacyGlobalDiForExtensionApi } from "@k8slens/legacy-global-di";
import removeWeblinkInjectable from "../../features/weblinks/common/remove.injectable";
import type { CatalogEntityContextMenuContext, CatalogEntityMetadata, CatalogEntityStatus } from "../catalog";
import type { CatalogEntitySpec } from "../catalog/catalog-entity";
import { CatalogCategory, CatalogEntity, categoryVersion } from "../catalog/catalog-entity";
import productNameInjectable from "../vars/product-name.injectable";
@ -15,7 +16,7 @@ export interface WebLinkStatus extends CatalogEntityStatus {
phase: WebLinkStatusPhase;
}
export interface WebLinkSpec {
export interface WebLinkSpec extends CatalogEntitySpec {
url: string;
}

View File

@ -5,7 +5,7 @@
import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn from "@async-fn/jest";
import type { AuthorizationV1Api, V1SubjectRulesReviewStatus } from "@kubernetes/client-node";
import type { AuthorizationV1Api, V1SelfSubjectRulesReview, V1SubjectRulesReviewStatus } from "@kubernetes/client-node";
import type { DiContainer } from "@ogre-tools/injectable";
import type { IncomingMessage } from "http";
import { anyObject } from "jest-mock-extended";
@ -192,8 +192,8 @@ describe("requestNamespaceListPermissions", () => {
body: {
status,
spec: {},
},
value: null as unknown as IncomingMessage,
} as V1SelfSubjectRulesReview,
response: null as unknown as IncomingMessage,
});
});

View File

@ -3,38 +3,17 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectionToken } from "@ogre-tools/injectable";
import type { RequiredKeysOf } from "type-fest";
import type { Route } from "./front-end-route-injection-token";
type InferParametersFrom<TRoute> = TRoute extends Route<infer TParameters>
type InferParametersFrom<TRoute> = TRoute extends Route<infer TParameters extends object>
? TParameters
: never;
type RequiredKeys<T> = Exclude<
{
[K in keyof T]: T extends Record<K, T[K]> ? K : never;
}[keyof T],
undefined
>;
type ObjectContainingNoRequired<T> = T extends void
? never
: (
RequiredKeys<T> extends []
? Record<string, never>
: never
);
type ObjectContainsNoRequired<T> = T extends ObjectContainingNoRequired<T>
? true
: false;
// TODO: Missing types for:
// - Navigating to route without parameters, with parameters
// - Navigating to route with required parameters, without parameters
type Parameters<TParameters> = TParameters extends void
type Parameters<TParameters extends object> = TParameters extends void
? { parameters?: undefined }
: (
ObjectContainsNoRequired<TParameters> extends true
RequiredKeysOf<TParameters> extends never
? { parameters?: TParameters }
: { parameters: TParameters }
);

View File

@ -16,8 +16,7 @@ const navigateToCatalogInjectable = getInjectable({
const navigateToRoute = di.inject(navigateToRouteInjectionToken);
const catalogRoute = di.inject(catalogRouteInjectable);
return (parameters) =>
navigateToRoute(catalogRoute, {
return (parameters) => navigateToRoute(catalogRoute, {
parameters,
});
},

View File

@ -3,8 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { WriteFileOptions } from "fs";
import type { ReadOptions } from "fs-extra";
import type { CopyOptions, EnsureOptions, ReadOptions, WriteOptions } from "fs-extra";
import fse from "fs-extra";
export type FileSystemFunctions = ReturnType<(typeof fsInjectable)["instantiate"]>;
@ -45,7 +44,7 @@ const fsInjectable = getInjectable({
readFile,
readJson: readJson as (file: string, options?: ReadOptions | BufferEncoding) => Promise<unknown>,
writeFile,
writeJson: writeJson as (file: string, value: unknown, options?: string | WriteFileOptions) => Promise<void>,
writeJson: writeJson as (file: string, value: unknown, options?: string | WriteOptions) => Promise<void>,
pathExists,
readdir,
readFileSync,
@ -56,8 +55,8 @@ const fsInjectable = getInjectable({
lstat,
rm,
access,
copy: copy as (src: string, dest: string, options?: fse.CopyOptions) => Promise<void>,
ensureDir: ensureDir as (path: string, options?: number | fse.EnsureOptions ) => Promise<void>,
copy: copy as (src: string, dest: string, options?: CopyOptions) => Promise<void>,
ensureDir: ensureDir as (path: string, options?: number | EnsureOptions ) => Promise<void>,
ensureDirSync,
createReadStream,
stat,

View File

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

View File

@ -8,10 +8,10 @@ import type { RequestInit } from "@k8slens/node-fetch";
import lensProxyCertificateInjectable from "../certificate/lens-proxy-certificate.injectable";
import fetchInjectable from "../fetch/fetch.injectable";
import { loggerInjectionToken } from "@k8slens/logger";
import type { JsonApiConfig, JsonApiData, JsonApiDependencies, JsonApiParams } from "@k8slens/json-api";
import type { JsonApiConfig, JsonApiDependencies, JsonApiParams } from "@k8slens/json-api";
import { JsonApi } from "@k8slens/json-api";
export type CreateJsonApi = <Data = JsonApiData, Params extends JsonApiParams<Data> = JsonApiParams<Data>>(config: JsonApiConfig, reqInit?: RequestInit) => JsonApi<Data, Params>;
export type CreateJsonApi = <Data = unknown, Params extends JsonApiParams<Data> = JsonApiParams<Data>>(config: JsonApiConfig, reqInit?: RequestInit) => JsonApi<Data, Params>;
const createJsonApiInjectable = getInjectable({
id: "create-json-api",

View File

@ -31,7 +31,7 @@ const requestCreateHelmReleaseInjectable = getInjectable({
return apiBase.post(requestCreateEndpoint.compile({}), {
data: {
chart: `${repo}/${chart}`,
values: yaml.load(values),
values: yaml.load(values) as object,
...data,
},
});

View File

@ -46,7 +46,7 @@ const requestMetricsInjectable = getInjectable({
function requestMetrics(query: string, params?: RequestMetricsParams): Promise<MetricData>;
function requestMetrics(query: string[], params?: RequestMetricsParams): Promise<MetricData[]>;
function requestMetrics<Keys extends string>(query: Record<Keys, Partial<Record<string, string>>>, params?: RequestMetricsParams): Promise<Record<Keys, MetricData>>;
async function requestMetrics(query: string | string[] | Partial<Record<string, Partial<Record<string, string>>>>, params: RequestMetricsParams = {}): Promise<MetricData | MetricData[] | Partial<Record<string, MetricData>>> {
async function requestMetrics(metricsQuery: string | string[] | Partial<Record<string, Partial<Record<string, string>>>>, params: RequestMetricsParams = {}): Promise<MetricData | MetricData[] | Partial<Record<string, MetricData>>> {
const { range = 3600, step = 60, namespace } = params;
let { start, end } = params;
@ -58,7 +58,7 @@ const requestMetricsInjectable = getInjectable({
}
return apiBase.post("/metrics", {
data: query,
data: metricsQuery,
query: {
start, end, step,
"kubernetes_namespace": namespace,

View File

@ -6,9 +6,10 @@ import { getInjectable } from "@ogre-tools/injectable";
import type { Patch } from "rfc6902";
import apiBaseInjectable from "../../api-base.injectable";
import type { AsyncResult, Result } from "@k8slens/utilities";
import { result } from "@k8slens/utilities";
import type { KubeJsonApiData } from "@k8slens/kube-object";
export type RequestKubeObjectPatch = (name: string, kind: string, ns: string | undefined, patch: Patch) => AsyncResult<KubeJsonApiData, string>;
export type RequestKubeObjectPatch = (name: string, kind: string, ns: string | undefined, patch: Patch) => AsyncResult<KubeJsonApiData, Error>;
const requestKubeObjectPatchInjectable = getInjectable({
id: "request-kube-object-patch",
@ -16,7 +17,7 @@ const requestKubeObjectPatchInjectable = getInjectable({
const apiBase = di.inject(apiBaseInjectable);
return async (name, kind, ns, patch) => {
const result = (await apiBase.patch("/stack", {
const patchResult = (await apiBase.patch("/stack", {
data: {
name,
kind,
@ -25,22 +26,14 @@ const requestKubeObjectPatchInjectable = getInjectable({
},
})) as Result<string, string>;
if (!result.isOk) {
return result;
if (!patchResult.isOk) {
return result.wrapError("Failed to patch kube object", patchResult);
}
try {
const response = JSON.parse(result.value) as KubeJsonApiData;
return {
isOk: true,
response,
};
return result.ok(JSON.parse(patchResult.value) as KubeJsonApiData);
} catch (error) {
return {
isOk: false,
error: String(error),
};
return result.error(new Error("Failed to parse response from patching kube object", { cause: error }));
}
};
},

View File

@ -5,9 +5,10 @@
import { getInjectable } from "@ogre-tools/injectable";
import apiBaseInjectable from "../../api-base.injectable";
import type { AsyncResult, Result } from "@k8slens/utilities";
import { result } from "@k8slens/utilities";
import type { KubeJsonApiData } from "@k8slens/kube-object";
export type RequestKubeObjectCreation = (resourceDescriptor: string) => AsyncResult<KubeJsonApiData, string>;
export type RequestKubeObjectCreation = (resourceDescriptor: string) => AsyncResult<KubeJsonApiData, Error>;
const requestKubeObjectCreationInjectable = getInjectable({
id: "request-kube-object-creation",
@ -15,24 +16,16 @@ const requestKubeObjectCreationInjectable = getInjectable({
const apiBase = di.inject(apiBaseInjectable);
return async (data) => {
const result = await apiBase.post("/stack", { data }) as Result<string, string>;
const postResult = await apiBase.post("/stack", { data }) as Result<string, string>;
if (!result.isOk) {
return result;
if (!postResult.isOk) {
return result.wrapError("Failed to create kube object", postResult);
}
try {
const response = JSON.parse(result.value) as KubeJsonApiData;
return {
isOk: true,
response,
};
return result.ok(JSON.parse(postResult.value) as KubeJsonApiData);
} catch (error) {
return {
isOk: false,
error: String(error),
};
return result.error(new Error("Failed to parse result from kube object creation", { cause: error }));
}
};
},

View File

@ -57,7 +57,7 @@ describe("with-error-suppression", () => {
});
describe("given decorated async function", () => {
let decorated: (a: string, b: string) => Promise<number> | Promise<void>;
let decorated: (a: string, b: string) => Promise<number | undefined>;
let toBeDecorated: AsyncFnMock<(a: string, b: string) => Promise<number>>;
beforeEach(() => {
@ -67,7 +67,7 @@ describe("with-error-suppression", () => {
});
describe("when called", () => {
let returnValuePromise: Promise<number> | Promise<void>;
let returnValuePromise: Promise<number | undefined>;
beforeEach(() => {
returnValuePromise = decorated("some-parameter", "some-other-parameter");

View File

@ -13,8 +13,8 @@ const withOrphanPromiseInjectable = getInjectable({
instantiate: (di) => {
const withErrorLoggingFor = di.inject(withErrorLoggingInjectable);
return <T extends (...args: unknown[]) => Promise<unknown>>(toBeDecorated: T) =>
(...args: Parameters<T>): void => {
return <Args extends unknown[]>(toBeDecorated: (...args: Args) => unknown) =>
(...args: Args): void => {
const decorated = pipeline(
toBeDecorated,
withErrorLoggingFor(() => "Orphan promise rejection encountered"),

View File

@ -5,7 +5,6 @@
import { runInAction } from "mobx";
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import type { FakeExtensionOptions } from "../../renderer/components/test-utils/get-extension-fake";
import getHashInjectable from "../../extensions/extension-loader/file-system-provisioner-store/get-hash.injectable";
import fsInjectable from "../../common/fs/fs.injectable";
@ -30,11 +29,8 @@ describe("configurable directories for extension files", () => {
});
describe("when extension with a specific store name is enabled", () => {
let testExtensionOptions: FakeExtensionOptions;
beforeEach(() => {
testExtensionOptions = {
beforeEach(async () => {
await builder.extensions.enable({
id: "some-extension",
name: "some-extension-name",
@ -48,9 +44,7 @@ describe("configurable directories for extension files", () => {
},
},
},
};
await builder.extensions.enable(testExtensionOptions);
});
});
it("creates extension directory for specific store name", async () => {
@ -65,11 +59,8 @@ describe("configurable directories for extension files", () => {
});
describe("when extension with no specific store name is enabled", () => {
let testExtensionOptions: FakeExtensionOptions;
beforeEach(() => {
testExtensionOptions = {
beforeEach(async () => {
await builder.extensions.enable({
id: "some-extension",
name: "some-extension-name",
@ -83,9 +74,7 @@ describe("configurable directories for extension files", () => {
},
},
},
};
await builder.extensions.enable(testExtensionOptions);
});
});
it("creates extension directory for package name", async () => {

View File

@ -182,8 +182,8 @@ export class ExtensionLoader {
ipcMainHandle(extensionLoaderFromMainChannel, () => [...this.toJSON()]);
ipcMainOn(extensionLoaderFromRendererChannel, (event, extensions: [LensExtensionId, InstalledExtension][]) => {
this.syncExtensions(extensions);
ipcMainOn(extensionLoaderFromRendererChannel, (event, extensions) => {
this.syncExtensions(extensions as [LensExtensionId, InstalledExtension][]);
});
}
@ -205,8 +205,8 @@ export class ExtensionLoader {
};
void requestExtensionLoaderInitialState().then(extensionListHandler);
ipcRendererOn(extensionLoaderFromMainChannel, (event, extensions: [LensExtensionId, InstalledExtension][]) => {
extensionListHandler(extensions);
ipcRendererOn(extensionLoaderFromMainChannel, (event, extensions) => {
extensionListHandler(extensions as [LensExtensionId, InstalledExtension][]);
});
}

View File

@ -5,7 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable";
import { registeredExtensionsInjectable } from "./registered-extensions.injectable";
import createPersistentStorageInjectable from "../../../features/persistent-storage/common/create.injectable";
import { action } from "mobx";
import { runInAction } from "mobx";
import { object } from "@k8slens/utilities";
import storeMigrationVersionInjectable from "../../../common/vars/store-migration-version.injectable";
@ -21,7 +21,7 @@ const fileSystemProvisionerStoreInjectable = getInjectable({
configName: "lens-filesystem-provisioner-store",
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
projectVersion: storeMigrationVersion,
fromStore: action(({ extensions = {}}) => {
fromStore: ({ extensions = {}}) => runInAction(() => {
registeredExtensions.replace(object.entries(extensions));
}),
toJSON: () => ({

View File

@ -11,6 +11,7 @@ import type { PodStatus } from "@k8slens/kube-object";
import { Pod } from "@k8slens/kube-object";
import type { RequestMetrics } from "../../../common/k8s-api/endpoints/metrics.api/request-metrics.injectable";
import requestMetricsInjectable from "../../../common/k8s-api/endpoints/metrics.api/request-metrics.injectable";
import requestPodMetricsByNamespaceInjectable from "../../../renderer/components/workloads-pods/list-pod-metrics.injectable";
describe("workloads / pods", () => {
let rendered: RenderResult;
@ -19,7 +20,10 @@ describe("workloads / pods", () => {
beforeEach(async () => {
builder = await getApplicationBuilder().setEnvironmentToClusterFrame();
builder.namespaces.add("default");
await builder.beforeWindowStart(() => {
await builder.beforeWindowStart(({ windowDi }) => {
windowDi.override(requestPodMetricsByNamespaceInjectable, () => () => Promise.resolve([]));
});
await builder.afterWindowStart(() => {
builder.allowKubeResource({
apiName: "pods",
group: "",

View File

@ -0,0 +1,20 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { PodMetrics } from "@k8slens/kube-object";
import { getInjectable } from "@ogre-tools/injectable";
import podMetricsApiInjectable from "../../../common/k8s-api/endpoints/pod-metrics.api.injectable";
export type RequestPodMetricsByNamespace = (namespace: string | undefined) => Promise<PodMetrics[] | null>;
const requestPodMetricsByNamespaceInjectable = getInjectable({
id: "request-pod-metrics-by-namespace",
instantiate: (di): RequestPodMetricsByNamespace => {
const podMetricsApi = di.inject(podMetricsApiInjectable);
return (namespace) => podMetricsApi.list({ namespace });
},
});
export default requestPodMetricsByNamespaceInjectable;

View File

@ -7,9 +7,9 @@ import podApiInjectable from "../../../common/k8s-api/endpoints/pod.api.injectab
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
import { getKubeStoreInjectable } from "../../../common/k8s-api/api-manager/kube-object-store-token";
import { PodStore } from "./store";
import podMetricsApiInjectable from "../../../common/k8s-api/endpoints/pod-metrics.api.injectable";
import clusterFrameContextForNamespacedResourcesInjectable from "../../cluster-frame-context/for-namespaced-resources.injectable";
import { loggerInjectionToken } from "@k8slens/logger";
import requestPodMetricsByNamespaceInjectable from "./list-pod-metrics.injectable";
const podStoreInjectable = getKubeStoreInjectable({
id: "pod-store",
@ -19,7 +19,7 @@ const podStoreInjectable = getKubeStoreInjectable({
const api = di.inject(podApiInjectable);
return new PodStore({
podMetricsApi: di.inject(podMetricsApiInjectable),
requestPodMetricsByNamespace: di.inject(requestPodMetricsByNamespaceInjectable),
context: di.inject(clusterFrameContextForNamespacedResourcesInjectable),
logger: di.inject(loggerInjectionToken),
}, api);

View File

@ -9,10 +9,11 @@ import type { KubeObjectStoreDependencies, KubeObjectStoreOptions } from "../../
import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store";
import { cpuUnitsToNumber, unitsToBytes } from "@k8slens/utilities";
import type { Pod, PodMetrics, KubeObject, NamespaceScopedMetadata } from "@k8slens/kube-object";
import type { PodApi, PodMetricsApi } from "@k8slens/kube-api";
import type { PodApi } from "@k8slens/kube-api";
import type { RequestPodMetricsByNamespace } from "./list-pod-metrics.injectable";
export interface PodStoreDependencies extends KubeObjectStoreDependencies {
readonly podMetricsApi: PodMetricsApi;
requestPodMetricsByNamespace: RequestPodMetricsByNamespace;
}
export class PodStore extends KubeObjectStore<Pod, PodApi> {
@ -28,7 +29,7 @@ export class PodStore extends KubeObjectStore<Pod, PodApi> {
async loadKubeMetrics(namespace?: string) {
try {
const metrics = await this.dependencies.podMetricsApi.list({ namespace });
const metrics = await this.dependencies.requestPodMetricsByNamespace(namespace);
this.kubeMetrics.replace(metrics ?? []);
} catch (error) {

View File

@ -7,7 +7,6 @@ import { Agent as HttpAgent } from "http";
import { Agent as HttpsAgent } from "https";
import { merge } from "lodash";
import { stringify } from "querystring";
import type { Patch } from "rfc6902";
import type { PartialDeep, ValueOf } from "type-fest";
import { EventEmitter } from "@k8slens/event-emitter";
import type { Logger } from "@k8slens/logger";
@ -16,8 +15,6 @@ import type { RequestInit, Response } from "@k8slens/node-fetch";
import type { Defaulted } from "@k8slens/utilities";
import { isArray, isObject, isString, json } from "@k8slens/utilities";
export type JsonApiData = Record<string, never>;
export interface JsonApiError {
code?: number;
message?: string;
@ -106,7 +103,7 @@ export class JsonApiErrorParsed {
}
}
export class JsonApi<Data = JsonApiData, Params extends JsonApiParams<Data> = JsonApiParams<Data>> {
export class JsonApi<Data = unknown, Params extends { data?: unknown } = { data?: unknown }> {
static readonly reqInitDefault = {
headers: {
"content-type": "application/json",
@ -188,7 +185,7 @@ export class JsonApi<Data = JsonApiData, Params extends JsonApiParams<Data> = Js
patch<OutData = Data, Query = QueryParams>(
path: string,
params?: ParamsAndQuery<Omit<Params, "data">, Query> & { data?: Patch | PartialDeep<Data> },
params?: ParamsAndQuery<Params, Query>,
reqInit: RequestInit = {},
) {
return this.request<OutData, Query>(path, params, { ...reqInit, method: "patch" });
@ -204,7 +201,7 @@ export class JsonApi<Data = JsonApiData, Params extends JsonApiParams<Data> = Js
protected async request<OutData, Query = QueryParams>(
path: string,
params: (ParamsAndQuery<Omit<Params, "data">, Query> & { data?: unknown }) | undefined,
params: ParamsAndQuery<Params, Query> | undefined,
init: Defaulted<RequestInit, "method">,
) {
let reqUrl = `${this.config.serverAddress}${this.config.apiBase}${path}`;