/** * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ import type { Cluster } from "../../common/cluster/cluster"; import type http from "http"; import type httpProxy from "http-proxy"; import type { LensApiResultContentType } from "./router-content-types"; import type { URLSearchParams } from "url"; import type { SafeParseReturnType } from "zod"; declare const emptyObjectSymbol: unique symbol; export interface EmptyObject {[emptyObjectSymbol]?: never} export type InferParam< T extends string, PathParams, > = T extends `{${infer P}?}` ? PathParams & Partial> : T extends `{${infer P}}` ? PathParams & Record : PathParams; export type InferParamFromPath

= P extends `${string}/{${infer B}*}${infer Tail}` ? Tail extends "" ? Record : never : P extends `${infer A}/${infer B}` ? InferParam> : InferParam; export interface LensApiRequest { path: Path; payload: unknown; params: string extends Path ? Partial> : InferParamFromPath; cluster: Cluster | undefined; query: URLSearchParams; raw: { req: http.IncomingMessage; res: http.ServerResponse; }; } export interface ClusterLensApiRequest extends LensApiRequest { cluster: Cluster; } export interface LensApiResult { statusCode?: number; response?: Response; error?: string | Error; contentType?: LensApiResultContentType; headers?: Partial>; proxy?: httpProxy; } export type RouteResponse = | LensApiResult | void; export interface RouteHandler{ (request: LensApiRequest): RouteResponse | Promise>; } export interface BaseRoutePaths { path: Path; method: "get" | "post" | "put" | "patch" | "delete"; } export interface PayloadValidator { safeParse(payload: unknown): SafeParseReturnType; } export interface ValidatorBaseRoutePaths extends BaseRoutePaths { payloadSchema: PayloadValidator; } export interface Route extends BaseRoutePaths { handler: RouteHandler; } export interface BindHandler { (handler: RouteHandler): Route; } export function route(parts: BaseRoutePaths): BindHandler { return (handler) => ({ ...parts, handler, }); } export interface ClusterRouteHandler{ (request: ClusterLensApiRequest): RouteResponse | Promise>; } export interface BindClusterHandler { (handler: ClusterRouteHandler): Route; } export function clusterRoute(parts: BaseRoutePaths): BindClusterHandler { return (handler) => ({ ...parts, handler: ({ cluster, ...rest }) => { if (!cluster) { return { error: "Cluster missing", statusCode: 400, }; } return handler({ cluster, ...rest }); }, }); } export interface ValidatedClusterLensApiRequest extends ClusterLensApiRequest { payload: Payload; } export interface ValidatedClusterRouteHandler { (request: ValidatedClusterLensApiRequest): RouteResponse | Promise>; } export interface BindValidatedClusterHandler { (handler: ValidatedClusterRouteHandler): Route; } export function payloadWithSchemaClusterRoute({ payloadSchema: payloadValidator, ...parts }: ValidatorBaseRoutePaths): BindValidatedClusterHandler { const boundClusterRoute = clusterRoute(parts); return (handler) => boundClusterRoute(({ payload, ...rest }) => { const validationResult = payloadValidator.safeParse(payload); if (!validationResult.success) { return { error: validationResult.error, statusCode: 400, }; } return handler({ payload: validationResult.data, ...rest, }); }); }