/// import { IncomingHttpHeaders } from 'http'; import { ClientDuplexStream, ClientReadableStream, ClientWritableStream, type ServiceError } from '@grpc/grpc-js'; import { HandlerType } from '@grpc/grpc-js/build/src/server-call'; import { AxiosInterceptorManager, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'; import { IAxiosRetryConfig } from 'axios-retry'; import type { Request, Response } from 'express'; import * as protobufjs from 'protobufjs'; import type { GrpcContext } from '../components/grpc'; import { Lang } from '../constants'; import { GatewayContext } from './context'; import { AppErrorConstructor } from './error'; export interface GatewayRequest extends Request { id: string; ctx: Context; } export interface GatewayResponse extends Response { } export interface Headers { [key: string]: any; } export interface EndpointsConfig { [key: string]: ActionEndpoint; } export type AuthHeadersFunc = (serviceName: string) => Record | undefined; export interface ApiActionConfig { requestId: string; headers: Headers; args: TRequestData; ctx: Context; timeout?: number; retries?: number; callback?: (response: TResponseData) => void; authArgs?: Record; userId?: string; abortSignal?: AbortSignal; } export interface GRPCActionData { [key: string]: unknown; } export type SendStats = (stats: Stats, headers: IncomingHttpHeaders, ctx: Context, meta: { debugHeaders: Headers; }) => void; export interface Stats { service: string; action: string; restStatus: number; grpcStatus?: number; responseSize: number; requestId: string; requestTime: number; requestMethod: string; requestUrl: string; timestamp: number; userId?: string; traceId: string; } export type ControllerType = 'rest' | 'grpc'; export interface GatewayError { status: number; message: string; code: string; details?: { title?: string; description?: string; } & Record; debug?: any; requestId?: string; } export type GrpcRetryCondition = (error: ServiceError) => boolean; export type AxiosRetryCondition = IAxiosRetryConfig['retryCondition']; export type ProxyHeadersFunctionExtra = { service: string; action: string; protopath?: string; protokey?: string; }; export type ProxyHeadersFunction = (headers: IncomingHttpHeaders, type: ControllerType, extra: ProxyHeadersFunctionExtra) => IncomingHttpHeaders; export type ProxyHeaders = string[] | ProxyHeadersFunction; export type ProxyResponseHeadersFunction = (headers: Headers, type: ControllerType) => Headers; export type ProxyResponseHeaders = string[] | ProxyResponseHeadersFunction; export type GetAuthHeadersParams> = { actionType: ControllerType; serviceName: string; requestHeaders: Headers; authArgs: AuthArgs | undefined; }; export type GetAuthHeaders> = (params: GetAuthHeadersParams) => Record | undefined; export type ResponseContentType = AxiosResponse['headers']['Content-Type']; export interface GatewayApiOptions { serviceName: string; timeout?: number; grpcRetryCondition?: GrpcRetryCondition; axiosRetryCondition?: AxiosRetryCondition; sendStats?: SendStats; grpcOptions?: object; grpcRecreateService?: boolean; axiosConfig?: AxiosRequestConfig; axiosInterceptors?: AxiosInterceptorsConfig; proxyHeaders?: ProxyHeaders; proxyDebugHeaders?: ProxyHeaders; validationSchema?: object; encodePathArgs?: boolean; expectedResponseContentType?: ResponseContentType | ResponseContentType[]; getAuthHeaders: GetAuthHeaders; } export interface ParamsOutput { body?: any; query?: { [key: string]: any; }; headers?: Headers; } export interface ResponseError extends AxiosResponse { } export interface ExtendedBaseActionEndpoint { path: string; } export interface ExtendedGrpcActionEndpoint extends ExtendedBaseActionEndpoint { insecure?: boolean; secureWithoutRootCert?: boolean; caCertificatePath?: string; clientCertificatePath?: string; clientKeyPath?: string; grpcOptions?: object; } export interface ExtendedRestActionEndpoint extends ExtendedBaseActionEndpoint { axiosConfig?: AxiosRequestConfig; } export type ExtendedActionEndpoint = ExtendedGrpcActionEndpoint | ExtendedRestActionEndpoint; export type ActionEndpoint = string | ExtendedActionEndpoint; export interface ApiServiceBaseActionConfig { getAuthHeaders?: GetAuthHeaders; params?: (args: TParams, headers: Headers, config: ApiParamsConfig) => Promise | ParamsOutput; endpoint?: string | ((endpoints: EndpointsConfig | undefined, args: TParams) => string); transformResponseData?: (data: TOutput, config: ApiTransformResponseDataConfig) => Promise | TTransformed; transformResponseError?: (error: ResponseError, config: ApiTransformResponseErrorConfig) => Promise | GatewayError; validationSchema?: object; timeout?: number; retries?: number; idempotency?: boolean; proxyHeaders?: ProxyHeaders; proxyResponseHeaders?: ProxyResponseHeaders; metadata?: Record; abortOnClientDisconnect?: boolean; } export interface ApiServiceRestActionConfig extends ApiServiceBaseActionConfig { method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS'; path: (args: TParams) => string; paramsSerializer?: AxiosRequestConfig['paramsSerializer']; responseType?: AxiosRequestConfig['responseType']; expectedResponseContentType?: ResponseContentType | ResponseContentType[]; maxRedirects?: number; axiosRetryCondition?: AxiosRetryCondition; } export interface ApiServiceBaseGrpcActionConfig extends ApiServiceBaseActionConfig { action: string; protoKey: string; insecure?: boolean; secureWithoutRootCert?: boolean; caCertificatePath?: string; clientCertificatePath?: string; clientKeyPath?: string; encodedFields?: string[]; type?: HandlerType; decodeAnyMessageProtoLoaderOptions?: protobufjs.IConversionOptions; } export interface ApiServiceFileGrpcActionConfig extends ApiServiceBaseGrpcActionConfig { protoPath: string; } export declare enum GrpcReflection { OnFirstRequest = 0, OnEveryRequest = 1 } export interface ApiServiceReflectGrpcActionConfig extends ApiServiceBaseGrpcActionConfig { reflection: GrpcReflection; reflectionRefreshSec?: number; } export type ApiServiceGrpcActionConfig = ApiServiceFileGrpcActionConfig | ApiServiceReflectGrpcActionConfig; export interface ApiServiceMixedExtra, Res extends GatewayResponse> { headers: Headers; lang: Lang; ctx: Context; config: GatewayConfig; grpcContext: GrpcContext; abortSignal?: AbortSignal; } export type ApiServiceMixedActionConfig, Res extends GatewayResponse, TOutput, TParams = undefined, TTransformed = TOutput> = (api: unknown, args: TParams, extra: ApiServiceMixedExtra) => Promise; export type ApiServiceActionConfig, Res extends GatewayResponse, TOutput, TParams = undefined, TTransformed = TOutput> = ApiServiceRestActionConfig | ApiServiceGrpcActionConfig | ApiServiceMixedActionConfig; export type ApiActionResponseType = T extends ApiServiceActionConfig ? R : never; export type ApiActionParams = T extends ApiServiceActionConfig ? R : never; export interface ApiParamsConfig { ctx: Context; } export interface ApiTransformResponseDataConfig { args: TParams; ctx: Context; headers?: Headers; } export interface ApiTransformResponseErrorConfig { args: TParams; ctx: Context; } export interface BaseSchema { [key: string]: { actions: Record>; serviceName?: string; endpoints?: Record>; getAuthHeaders?: GetAuthHeaders; getAuthArgs?: (req: Request, res: Response) => Record | undefined; }; } export interface SchemasByScope { [scope: string]: BaseSchema; } export type ApiByScope, Res extends GatewayResponse> = { [scope in keyof R]: GatewayApi; }; export type ApiWithRoot, Res extends GatewayResponse> = ApiByScope['root'] & ApiByScope; export interface GatewayActionHeaders { debugHeaders: Headers; } export interface GatewayActionUnaryResponse extends GatewayActionHeaders { responseData: ApiActionResponseType; responseHeaders?: Headers; } export interface GatewayActionClientStreamResponse extends GatewayActionHeaders { stream: ClientWritableStream>; } export interface GatewayActionServerStreamResponse extends GatewayActionHeaders { stream: ClientReadableStream>; } export interface GatewayActionDuplexStreamResponse extends GatewayActionHeaders { stream: ClientDuplexStream, ApiActionResponseType>; } export type GatewayActionResponseData, Res extends GatewayResponse, TAction extends ApiServiceActionConfig> = TAction extends ApiServiceGrpcActionConfig ? TAction['type'] extends 'clientStream' ? GatewayActionClientStreamResponse : TAction['type'] extends 'serverStream' ? GatewayActionServerStreamResponse : TAction['type'] extends 'bidi' ? GatewayActionDuplexStreamResponse : GatewayActionUnaryResponse : GatewayActionUnaryResponse; type GatewayAction, Res extends GatewayResponse, TAction extends ApiServiceActionConfig> = undefined extends ApiActionParams ? (params?: ApiActionConfig, ApiActionResponseType>) => Promise> : (params: ApiActionConfig, ApiActionResponseType>) => Promise>; export type GatewayApi, Res extends GatewayResponse> = { [S in keyof T]: { [A in keyof T[S]['actions']]: GatewayAction; }; }; type ContextAction = undefined extends ApiActionParams ? (params?: ApiActionParams) => Promise> : (params: ApiActionParams) => Promise>; export type ContextApi = { [S in keyof T]: { [A in keyof T[S]['actions']]: ContextAction; }; }; export type ContextApiByScope = { [scope in keyof R]: ContextApi; }; export type ContextApiWithRoot = ContextApiByScope['root'] & ContextApiByScope; interface OnUnknownActionData { service?: string; action?: string; } type AxiosInterceptorUseParams = Parameters['use']>; interface AxiosInterceptorConfig { callback: AxiosInterceptorUseParams[0]; errorCallback?: AxiosInterceptorUseParams[1]; } export interface AxiosInterceptorsConfig { request?: AxiosInterceptorConfig>[]; response?: AxiosInterceptorConfig>[]; } export interface GatewayConfig, Res extends GatewayResponse> { installation?: string; env?: string; actions?: string[]; timeout?: number; grpcRetryCondition?: GrpcRetryCondition; axiosRetryCondition?: AxiosRetryCondition; grpcOptions?: object; grpcRecreateService?: boolean; axiosConfig?: AxiosRequestConfig; axiosInterceptors?: AxiosInterceptorsConfig; onUnknownAction?: (req: Req, res: Res, data: OnUnknownActionData) => any; onBeforeAction?: (req: Req, res: Res, scope: string, service: string, action: string, config?: ApiServiceActionConfig) => any; onRequestSuccess?: (req: Req, res: Res, data: any) => any; onRequestFailed?: (req: Req, res: Res, error: any) => any; sendStats?: SendStats; includeProtoRoots?: string[]; caCertificatePath: string | null; clientCertificatePath?: string | null; clientKeyPath?: string | null; proxyHeaders: ProxyHeaders; proxyDebugHeaders?: ProxyHeaders; withDebugHeaders?: boolean | ((req: Req, res: Res) => boolean); validationSchema?: object; encodePathArgs?: boolean; getAuthArgs: (req: Req, res: Res) => Record | undefined; getAuthHeaders: GetAuthHeaders; ErrorConstructor: AppErrorConstructor; } export {};