@duongtrungnguyen/nestro
Version:
Service registry for Nest JS
353 lines (325 loc) • 14.7 kB
TypeScript
import { NestExpressApplication } from '@nestjs/platform-express';
import { Server as Server$1 } from 'https';
import { Server, IncomingMessage, ServerResponse } from 'http';
import { OnModuleInit, OnModuleDestroy, Type, NestApplicationOptions, RequestMethod, NestMiddleware, CanActivate, DynamicModule, NestModule, MiddlewareConsumer, RawBodyRequest } from '@nestjs/common';
import { Socket } from 'net';
import { URL as URL$1 } from 'url';
import { Request, Response } from 'express';
import { ModuleRef } from '@nestjs/core';
type HttpProtocols = "http" | "https";
type WsPRotocols = "wss" | "ws";
type InstanceStatus = "ON" | "OFF";
type Instance = {
host: string;
port: number;
metadata?: Record<string, any>;
swaggerJsonPath?: string;
};
type ServiceConfig = Partial<Instance> & {
name: string;
secure?: boolean;
};
type Service = Instance & {
name: string;
protocol: HttpProtocols;
status: InstanceStatus;
};
type NestroApplication<TServer extends Server | Server$1 = Server> = NestExpressApplication<TServer> & {
listen: (port?: number) => Promise<TServer>;
};
type LoadBalancingStrategy = "random" | "round-robin" | "least-connections" | "weighted-round-robin" | "response-time";
type LoadBalancingConfig = {
strategy?: LoadBalancingStrategy;
refreshInterval?: number;
maxRetries?: number;
};
interface ILoadBalancer {
selectInstance(instances: Service[]): Service | null;
trackConnectionStart?(instanceId: string): void;
trackConnectionEnd?(instanceId: string): void;
reset?(): void;
}
declare class DiscoveryService implements OnModuleInit, OnModuleDestroy {
private readonly loadBalancingConfigs;
private readonly loadBalancer;
private services;
private refreshIntervalId;
private serverBaseUrl;
constructor(loadBalancingConfigs: LoadBalancingConfig, loadBalancer: ILoadBalancer, serverInfo: ServerInfo);
onModuleInit(): Promise<void>;
onModuleDestroy(): void;
loadInstances(): Promise<void>;
getServices(): Map<string, Service[]>;
getInstances(serviceName: string): Service[];
discover<T>(serviceName: string, callback: (instance: Service, tryAnotherInstance: VoidFunction) => Promise<T> | T): Promise<T>;
private getInstanceId;
}
declare enum DiscoveryErrorCode {
SERVICE_NOT_FOUND = "SERVICE_NOT_FOUND",
ALL_INSTANCES_FAILED = "ALL_INSTANCES_FAILED"
}
declare class DiscoveryError extends Error {
readonly message: string;
readonly code: DiscoveryErrorCode;
constructor(message: string, code: DiscoveryErrorCode);
}
type KeyServiceOptions = {
initKeys: boolean;
publicKeyPath: string;
privateKeyPath: string;
};
type SecurityModuleConfig = Partial<KeyServiceOptions>;
type ServerConfig = {
host?: string;
port?: number;
secure?: boolean;
} | URL;
type ServerInfo = {
host?: string;
port?: number;
protocol?: HttpProtocols;
};
type ClientServiceConfig = {
server: ServerConfig;
client: ServiceConfig;
};
type GatewayOptions = {
swagger?: {
path: string;
title: string;
version: string;
description: string;
jsonPath?: string;
};
};
type GatewayConfig = GatewayOptions;
type NestroClientConfig = ClientServiceConfig & {
security?: SecurityModuleConfig;
loadbalancing?: LoadBalancingConfig;
enableSecurity?: boolean;
gateway?: GatewayConfig;
};
declare function CommunicateRequest(serviceName?: string): (_: any, __: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
declare function getFreePort(): Promise<number>;
declare function getDefaultHost(): string;
declare function createNestroApplication(AppModule: Type<any>, config: NestroClientConfig, applicationOptions?: NestApplicationOptions): Promise<NestroApplication>;
declare abstract class CommunicationTemplate {
_discoveryService: DiscoveryService;
targetService: string;
constructor(discoveryService: DiscoveryService, targetService: string);
}
type HookRoute = {
path: string;
method: RequestMethod;
};
type RequestHook<T> = {
instance: Type<T>;
includes?: Array<HookRoute>;
excludes?: Array<HookRoute>;
} | Type<T>;
type GatewayRoutingConfig = {
route: string;
service?: string;
pathRewrite?: {
[key: string]: string;
};
timeout?: number;
protocol?: "http" | "ws";
target?: string;
middlewares?: Array<RequestHook<NestMiddleware>>;
guards?: Array<RequestHook<CanActivate>>;
};
type GatewayRoutingConfigFunction = (builder: GatewayConfigBuilder) => DynamicModule | Promise<DynamicModule>;
type ProxyTarget = {
host?: string;
hostname?: string;
port?: number;
path?: string;
protocol?: string;
socketPath?: string;
pfx?: string | Buffer | Array<string | Buffer>;
key?: string | Buffer | Array<string | Buffer>;
cert?: string | Buffer | Array<string | Buffer>;
ca?: string | Buffer | Array<string | Buffer>;
secureProtocol?: string;
passphrase?: string;
ciphers?: string;
};
type ProxyOptions = {
target?: string | URL$1 | ProxyTarget;
changeOrigin?: boolean;
xfwd?: boolean;
pathRewrite?: Record<string, string | ((path: string, req: IncomingMessage) => string)>;
preserveHeaderKeyCase?: boolean;
buffer?: Buffer | string | Record<string, any>;
proxyTimeout?: number;
secure?: boolean;
timeout?: number;
localAddress?: string;
prependPath?: boolean;
toProxy?: boolean;
ignorePath?: boolean;
cookieDomainRewrite?: string | Record<string, string | null>;
cookiePathRewrite?: string | Record<string, string | null>;
router?: Record<string, string | URL$1 | ProxyTarget>;
};
type OutgoingOptions = {
host?: string;
hostname?: string;
socketPath?: string;
port?: number;
path?: string;
method?: string;
headers?: Record<string, string | string[] | undefined>;
agent?: any;
localAddress?: string;
pfx?: string | Buffer | Array<string | Buffer>;
key?: string | Buffer | Array<string | Buffer>;
passphrase?: string;
cert?: string | Buffer | Array<string | Buffer>;
ca?: string | Buffer | Array<string | Buffer>;
ciphers?: string;
secureProtocol?: string;
rejectUnauthorized?: boolean;
};
interface ProxyCallbacks {
onStart?: (req: IncomingMessage, res: ServerResponse, target: string | URL$1 | ProxyTarget | undefined) => void;
onProxyReq?: (proxyReq: any, req: IncomingMessage, res: ServerResponse, socket: Socket) => void;
onProxyReqWs?: (proxyReq: any, req: IncomingMessage, socket: Socket, options: ProxyOptions, head: Buffer) => void;
onProxyRes?: (proxyRes: IncomingMessage, req: IncomingMessage, res: ServerResponse) => void;
onOpen?: (proxySocket: Socket) => void;
onClose?: (proxyRes: IncomingMessage, proxySocket: Socket, proxyHead: Buffer) => void;
onEnd?: (req: IncomingMessage, res: ServerResponse, proxyRes: IncomingMessage) => void;
onError?: (err: Error, req: IncomingMessage, res: ServerResponse | Socket, target?: string | URL$1 | ProxyTarget) => void;
onConnectFailed?: (err: Error) => void;
}
declare class GatewayConfigBuilder {
private globalMiddlewares;
private globalGuards;
private routes;
private providers;
private route;
httpRoute(config: Omit<GatewayRoutingConfig, "protocol">): this;
wsRoute(config: Omit<GatewayRoutingConfig, "protocol">): this;
useGlobalMiddleware(...middlewares: Array<Type<NestMiddleware>>): this;
useGlobalGuard(...guards: Array<Type<CanActivate>>): this;
private registerRequestHookProviders;
build(): DynamicModule;
}
interface IGatewayConfig {
build: GatewayRoutingConfigFunction;
}
declare class GatewayModule implements NestModule {
static routes: Array<GatewayRoutingConfig>;
static globalMiddlewares: Array<Type<NestMiddleware>>;
static builder(): GatewayConfigBuilder;
static register(config: Type<IGatewayConfig> | GatewayRoutingConfigFunction): DynamicModule | Promise<DynamicModule>;
configure(consumer: MiddlewareConsumer): void;
}
declare function ProxyForward(options?: ProxyOptions): MethodDecorator;
declare class RouteHandleService {
private readonly routesConfig;
private readonly globalGuards;
private readonly moduleRef;
constructor(routesConfig: GatewayRoutingConfig[], globalGuards: Array<Type<CanActivate>>, moduleRef: ModuleRef);
findMatchingRoute(path: string): GatewayRoutingConfig | undefined;
checkGuards(guards: Array<RequestHook<CanActivate>>, req: Request, res: Response): Promise<boolean>;
private shouldApplyHook;
private executeGuard;
private createExecutionContext;
}
declare enum ProxyErrorType {
CONNECTION_FAILED = "CONNECTION_FAILED",
TIMEOUT = "TIMEOUT",
TARGET_NOT_FOUND = "TARGET_NOT_FOUND",
INVALID_RESPONSE = "INVALID_RESPONSE",
NETWORK_ERROR = "NETWORK_ERROR",
CONFIGURATION_ERROR = "CONFIGURATION_ERROR",
UNKNOWN = "UNKNOWN"
}
declare class ProxyError extends Error {
readonly type: ProxyErrorType;
readonly statusCode: number;
private readonly timestamp;
constructor(message: string, type: ProxyErrorType, statusCode?: number);
toJson(): string;
}
declare abstract class BaseProxyService {
protected readonly discoveryService: DiscoveryService;
constructor(discoveryService: DiscoveryService);
abstract proxyRequest(req: RawBodyRequest<Request>, res: Response, routeConfig: GatewayRoutingConfig): Promise<void>;
abstract handleProxy(req: IncomingMessage, res: ServerResponse, options: ProxyOptions, callbacks: ProxyCallbacks): void;
protected executeProxy(req: RawBodyRequest<Request> | Request, res: Response, options: ProxyOptions, proxyFn: (req: IncomingMessage, res: ServerResponse | Socket, options: ProxyOptions, callbacks?: ProxyCallbacks) => void, callbacks?: ProxyCallbacks): Promise<void>;
protected validateRouteConfig(routeConfig: GatewayRoutingConfig): void;
protected buildProxyOptions(routeConfig: GatewayRoutingConfig, defaultOptions?: Partial<ProxyOptions>): ProxyOptions;
protected handleDiscoveryError(error: Error): ProxyError;
addForwardedHeaders(req: IncomingMessage, xfwd?: boolean, isWebSocket?: boolean): void;
protected normalizeOptions(options: ProxyOptions, path: string): ProxyOptions;
protected handleError(err: Error, req: IncomingMessage, res: ServerResponse | Socket, target?: any, onError?: (err: Error, req: IncomingMessage, res: ServerResponse | Socket, target?: any) => void): void;
private categorizeError;
}
declare class HttpProxyService extends BaseProxyService {
constructor(discoveryService: DiscoveryService);
proxyRequest(req: RawBodyRequest<Request>, res: Response, routeConfig: GatewayRoutingConfig): Promise<void>;
private proxyToService;
private proxyToTarget;
handleProxy(req: IncomingMessage, res: ServerResponse, options?: ProxyOptions, callbacks?: ProxyCallbacks): void;
private streamRequest;
getRequestBuffer(req: RawBodyRequest<Request>): Buffer | string | undefined;
private handleProxyRequest;
private handleProxyResponse;
private sendRequest;
private isConnectionError;
private copyHeaders;
private rewriteCookies;
}
declare class WsProxyService extends BaseProxyService {
constructor(discoveryService: DiscoveryService);
proxyRequest(req: RawBodyRequest<Request>, res: Response, routeConfig: GatewayRoutingConfig): Promise<void>;
private proxyToService;
private proxyToTarget;
private isConnectionError;
handleProxy(req: IncomingMessage, _: ServerResponse, options?: ProxyOptions, callbacks?: ProxyCallbacks): void;
private streamRequest;
private handleRequestCreationError;
private setupProxyRequestHandlers;
private handleWebSocketUpgrade;
private createHttpHeader;
}
declare class GatewayService {
private readonly httpProxyService;
private readonly wsProxyService;
private readonly routeHandleService;
constructor(httpProxyService: HttpProxyService, wsProxyService: WsProxyService, routeHandleService: RouteHandleService);
proxyRequest(req: RawBodyRequest<Request>, res: Response): Promise<void>;
executeWithOptions(req: RawBodyRequest<Request>, res: Response, options: ProxyOptions): void;
}
declare function setupOutgoing(outgoing: OutgoingOptions, options: ProxyOptions, req: IncomingMessage, forward?: string): OutgoingOptions;
declare function setupSocket(socket: Socket): Socket;
declare function hasEncryptedConnection(req: IncomingMessage): boolean;
declare function urlJoin(...args: string[]): string;
declare function rewriteCookieProperty(header: string | string[], config: Record<string, string | null>, property: string): string | string[];
declare function isSocketIORequest(req: IncomingMessage): boolean;
declare function isSocketRequest(req: Request): boolean;
type StorageOptions = {
heartbeatInterval?: number;
cleanupTTL?: number;
evictionThreshold?: number;
};
type StorageConfigs = Partial<StorageOptions>;
type ServiceInstance = Service & {
timestamp: number;
lastHeartbeatAt: number;
missedHeartbeats: number;
};
type NestroServerConfig = Partial<{
security: SecurityModuleConfig;
storage: StorageConfigs;
enableRegistryDashboard: boolean;
enableSecurity: boolean;
}>;
type RegisterResponse = {
heartbeatInterval: number;
};
declare function createNestroServer(AppModule: Type<any>, options?: NestroServerConfig, applicationOptions?: NestApplicationOptions): Promise<NestroApplication>;
export { type ClientServiceConfig, CommunicateRequest, CommunicationTemplate, DiscoveryError, DiscoveryErrorCode, DiscoveryService, type GatewayConfig, GatewayConfigBuilder, GatewayModule, type GatewayOptions, type GatewayRoutingConfig, type GatewayRoutingConfigFunction, GatewayService, type HookRoute, type HttpProtocols, HttpProxyService, type IGatewayConfig, type ILoadBalancer, type Instance, type InstanceStatus, type LoadBalancingConfig, type LoadBalancingStrategy, type NestroApplication, type NestroClientConfig, type NestroServerConfig, type OutgoingOptions, type ProxyCallbacks, ProxyError, ProxyErrorType, ProxyForward, type ProxyOptions, type ProxyTarget, type RegisterResponse, type RequestHook, RouteHandleService, type ServerConfig, type ServerInfo, type Service, type ServiceConfig, type ServiceInstance, type StorageConfigs, type StorageOptions, type WsPRotocols, WsProxyService, createNestroApplication, createNestroServer, getDefaultHost, getFreePort, hasEncryptedConnection, isSocketIORequest, isSocketRequest, rewriteCookieProperty, setupOutgoing, setupSocket, urlJoin };