/// import * as http from 'http'; import * as net from 'net'; import * as oas3 from 'openapi3-ts'; import { Context as KoaContext } from 'koa'; import { Callback, ParametersByLocation, ParametersMap, HttpIncomingMessage } from './basicTypes'; import { Readable } from 'stream'; import { ParameterLocations, ParameterLocation, ExegesisOptions } from '.'; import { BodyParser } from './bodyParser'; import { IValidationError, ValidatorFunction, ResponseValidationResult } from './validation'; export interface HttpHeaders { [header: string]: number | string | string[]; } export interface ExegesisResponse { statusCode: number; statusMessage: string | undefined; headers: HttpHeaders; body: Buffer | string | Readable | any; connection: net.Socket; ended: boolean; setStatus(status: number): this; status(status: number): this; setBody(body: any): this; /** * Set the value of a header. * @param header - the header to set. * @param value - the value to set the header to. */ header(header: string, value: number | string | string[] | undefined): this; set(header: string, value: number | string | string[] | undefined): this; json(json: any): this; end(): void; setHeader(name: string, value: number | string | string[] | undefined): void; getHeader(name: string): number | string | string[] | undefined; getHeaderNames(): string[]; getHeaders(): HttpHeaders; hasHeader(name: string): boolean; removeHeader(name: string): void; writeHead(statusCode: number, headers?: HttpHeaders): void; writeHead(statusCode: number, statusMessage?: string, headers?: HttpHeaders): void; } export interface ExegesisContextBase { readonly req: HttpIncomingMessage; readonly origRes: http.ServerResponse; readonly res: ExegesisResponse; api: any; security?: { [scheme: string]: AuthenticationSuccess; }; user?: any; parameterLocations?: ParameterLocations; makeError(statusCode: number, message: string): Error; makeValidationError(message: string, parameterLocation: ParameterLocation): Error; /** * Returns true if the response has already been sent. */ isResponseFinished(): boolean; } export interface ExegesisContext extends ExegesisContextBase { parameterLocations: ParameterLocations; params: ParametersByLocation>; requestBody: any; options: ExegesisOptions; } export interface ExegesisPluginContext extends ExegesisContextBase { getParams(): Promise>>; getParams(done: Callback>>): void; getRequestBody(): Promise; getRequestBody(done: Callback): void; } export interface OAS3ApiInfo { openApiDoc: oas3.OpenAPIObject; serverPtr: string | undefined; serverObject: oas3.ServerObject | undefined; pathItemPtr: string; pathItemObject: oas3.PathItemObject; operationPtr: string | undefined; operationObject: oas3.OperationObject | undefined; requestBodyMediaTypePtr: string | undefined; requestBodyMediaTypeObject: oas3.MediaTypeObject | undefined; } export declare type PromiseController = (context: ExegesisContext) => any; export declare type CallbackController = (context: ExegesisContext, done: Callback) => void; export declare type Controller = PromiseController | CallbackController; export interface ControllerModule { [operationId: string]: Controller; } export interface Controllers { [controllerName: string]: ControllerModule; } export interface AuthenticationFailure { type: "invalid" | "missing"; status?: number; message?: string; challenge?: string; } export interface AuthenticationSuccess { type: "success"; user?: any; roles?: string[] | undefined; scopes?: string[] | undefined; [name: string]: any; } export declare type AuthenticationResult = AuthenticationSuccess | AuthenticationFailure; export interface AuthenticatorInfo { in?: "query" | "header" | "cookie"; name?: string; scheme?: string; } export declare type PromiseAuthenticator = (context: ExegesisPluginContext, info: AuthenticatorInfo) => AuthenticationResult | undefined | Promise; export declare type CallbackAuthenticator = (context: ExegesisPluginContext, info: AuthenticatorInfo, done: Callback) => void; export declare type Authenticator = PromiseAuthenticator | CallbackAuthenticator; export interface Authenticators { [scheme: string]: Authenticator; } /** * Result returned by the exegesisRunner. */ export interface HttpResult { headers: HttpHeaders; status: number; body: NodeJS.ReadableStream | undefined; } /** * A function which takes in a request and response, and returns an HttpResult. * * @throws {ValidationError} - If a validation error occurs in the parameters or the body. * @throws {HttpError} - If a non-validation error occurs, and an HTTP error code is suggested. * @throws {Error} - If any other error occurs. */ export declare type ExegesisRunner = (req: http.IncomingMessage, res: http.ServerResponse, ctx: KoaContext) => Promise; export declare type ParsedParameterValidator = (parameterValues: ParametersByLocation>) => IValidationError[] | null; export interface ResolvedOperation { parseParameters: (() => ParametersByLocation>); validateParameters: ParsedParameterValidator; parameterLocations: ParameterLocations; bodyParser: BodyParser | undefined; validateBody: ValidatorFunction | undefined; exegesisControllerName: string | undefined; operationId: string | undefined; controllerModule: ControllerModule | undefined; controller: Controller | undefined; validateResponse(response: ExegesisResponse, validateDefaultResponses: boolean): ResponseValidationResult; authenticate(context: ExegesisContext): Promise<{ [scheme: string]: AuthenticationSuccess; } | undefined>; } export interface ResolvedPath { operation: ResolvedOperation | undefined; api: T; } export interface ApiInterface { /** * Resolve an incoming request. * * @param method - The HTTP method used (e.g. 'GET'). * @param url - The URL used to retrieve this request. * @param headers - Any headers sent along with the request. * @throws {ValidationError} if some parameters cannot be parsed. */ resolve(method: string, url: string, headers: http.IncomingHttpHeaders): ResolvedPath | undefined; } export interface ExegesisPluginInstance { /** * Called exactly once, before Exegesis "compiles" the API document. * Plugins must not modify apiDoc here. * * @param data.apiDoc - the API document. */ preCompile?: ((data: { apiDoc: any; }) => void | Promise) | ((data: { apiDoc: any; }, done: Callback) => void); /** * Called immediately after the routing phase. Note that this is * called before Exegesis verifies routing was valid - the * `pluginContext.api` object will have information about the * matched route, but will this information may be incomplete. * For example, for OAS3 we may have matched a route, but not * matched an operation within the route. Or we may have matched * an operation but that operation may have no controller defined. * (If we failed to match a route at all, this will not be called.) * * If your API added a route to the API document, this function is a * good place to write a reply. * * @param pluginContext - the plugin context. */ postRouting?: ((pluginContext: ExegesisPluginContext) => void | Promise) | ((pluginContext: ExegesisPluginContext, done: Callback) => void); /** * Called for each request, after security phase and before input * is parsed and the controller is run. This is a good place to * do extra security checks. The `exegesis-plugin-roles` plugin, * for example, generates a 403 response here if the authenticated * user has insufficient privliedges to access this path. * * Note that this function will not be called if a previous pluing * has already written a response. * * @param pluginContext - the plugin context. */ postSecurity?: ((pluginContext: ExegesisPluginContext) => void | Promise) | ((pluginContext: ExegesisPluginContext, done: Callback) => void); /** * Called immediately after the controller has been run, but before * any response validation. This is a good place to do custom * response validation. If you have to deal with something weird * like XML, this is where you'd handle it. * * This function can modify the contents of the response. * * @param context - The exegesis plugin context. */ postController?: ((pluginContext: ExegesisContext) => void | Promise) | ((pluginContext: ExegesisContext, done: Callback) => void); } export interface ExegesisPlugin { info: { name: string; }; makeExegesisPlugin(data: { apiDoc: any; }): ExegesisPluginInstance; }