UNPKG

@sigiljs/sigil

Version:

TypeScript-first Node.js HTTP framework offering schema-driven routing, modifier-based middleware, plugin extensibility, and flexible response templating

219 lines (218 loc) 8.46 kB
import { HttpMethod } from '@sigiljs/pathfinder'; import { BaseSchema, ObjectSchema } from '@sigiljs/seal'; import { SealDescriptor } from '@sigiljs/seal/types'; import { IncomingHttpHeaders, IncomingMessage } from 'node:http'; import { IncomingBody, IncomingFile, IncomingHeaders, IncomingSearchParams } from './requests/containers'; import { ClientIpInfo } from './requests/get-client-ip-info'; import { SigilResponse } from './responses'; import { Exception } from './responses/exceptions'; import { $InternalNamedSigilResponse } from './responses/sigil-response'; /** * Core internal types used by the Sigil framework. */ declare namespace Internal { /** * Namespace for request processing types. */ namespace Requests { /** * Extended Node.js IncomingMessage with enforced method, url, and headers. */ type VerifiedIncomingMessage = IncomingMessage & { method: HttpMethod; url: string; headers: IncomingHttpHeaders; }; /** * Basic result of parsing an HTTP request: body and any uploaded files. * * @template Body type of the parsed request body. */ interface RequestProcessorResponse<Body = unknown> { /** Parsed request body wrapper. */ body: IncomingBody<Body>; /** Array of uploaded files. */ files: IncomingFile[]; } /** * RequestProcessorResponse that may include Content-Type info. */ interface RequestProcessorResponseOptionalParams<Body = unknown> extends RequestProcessorResponse<Body> { /** Optional MIME type of the request payload. */ contentType?: string; } /** * Full parsed HTTP request descriptor including metadata and routing info. * * @template Body type of the request body. * @template Headers shape of expected headers. * @template SearchParams shape of expected query parameters. */ interface FullRequestProcessorResponse<Body = unknown, Headers = unknown, SearchParams = unknown> extends RequestProcessorResponseOptionalParams<Body> { /** Parsed headers container. */ headers: IncomingHeaders<Headers extends Record<any, any> ? Headers : {}>; /** HTTP method used. */ method: HttpMethod; /** Request protocol ("http" or "https"). */ protocol: "http" | "https"; /** Parsed query parameters. */ query: IncomingSearchParams<SearchParams extends Record<any, any> ? SearchParams : {}>; /** URL path of the request. */ path: string; /** Client IP information. */ remoteAddress: ClientIpInfo; /** Host header value. */ host: string; } /** * Possible return types from a route handler. * Can be a promise or a direct value. */ type HandlerResponse<T = SigilResponse | Exception | Record<any, any> | number | string | boolean | Buffer | null | Array<any>> = Promise<T> | T; /** * ClientRequest passed into route handlers, extends FullRequestProcessorResponse * and adds route path parameters. * * @template PathParams type of the parsed path parameters. */ interface ClientRequest<PathParams extends Record<string, string>, Body = unknown, Headers = unknown, SearchParams = unknown> extends FullRequestProcessorResponse<Body, Headers, SearchParams> { /** Parsed and coerced route parameters. */ params: PathParams & { [key: string]: string; }; } } /** * Namespace for route metadata and schema types. */ namespace Route { /** * Descriptor for a registered route, including path, method, and schema info. */ type RequestDescriptor = { /** Route path pattern. */ path: string; /** HTTP method for the route. */ method: HttpMethod; /** Flattened metadata of any validation schemas. */ flatSchema: FlatRequestSchema; /** Optional metadata about responses. */ metadata?: Partial<RequestMetadataDescriptor>; }; /** * Container for the individual ObjectSchemas for request segments. */ type SchemasContainer = { /** Body validation schema. */ body: ObjectSchema<any>; /** Headers validation schema. */ headers: ObjectSchema<any>; /** Query parameters schema. */ query: ObjectSchema<any>; /** Path parameters schema. */ params: ObjectSchema<any>; }; /** * Detailed metadata descriptor for responses associated with a route. */ type RequestMetadataDescriptor = { /** Textual description of the route. */ description: string; /** Array of possible response descriptors */ responses: Array<number | (new () => Exception) | $InternalNamedSigilResponse>; /** Example response payload. */ example: any; /** Deprecated flag. */ deprecated: boolean; /** External documentation links for this route. */ externalDocs: NonNullable<SealDescriptor["externalDocs"]>; /** Request summary */ summary: string; /** Describe security schemas used by this request */ security: Record<string, string[] | boolean>[] | Record<string, string[] | boolean> | string[] | string | null; }; /** * Flattened request schema mapping each segment to its plain object shape. */ type FlatRequestSchema = Partial<{ body: Record<string, any>; headers: Record<string, any>; query: Record<string, any>; params: Record<string, any>; }>; /** * Defines the structure of raw Seal schemas before flattening. */ interface RequestSchemaDescriptor { /** Body as a map of property to BaseSchema. */ body: { [key: string]: BaseSchema<any>; }; /** Headers as a map to StringSchema. */ headers: { [key: string]: BaseSchema<any>; }; /** Query params as map to StringSchema or OptionalSchema. */ query: { [key: string]: BaseSchema<any>; }; /** Route params as map to StringSchema or OptionalSchema. */ params: { [key: string]: BaseSchema<any>; }; } /** * Metadata descriptor for a validation schema itself (for docs). */ interface RouteDescriptor<Example = any> { /** Schema name. */ name: string; /** Human-readable description. */ description: string; /** Example value for this schema. */ example: Example; /** Default value. */ default: Example; /** Deprecated flag. */ deprecated: boolean; /** External docs link. */ externalDocs: NonNullable<SealDescriptor["externalDocs"]>; /** Allow unknown fields in schema */ allowUnknown: boolean; } } /** * Function signature for formatting a HandlerResponse into HTTP response data. */ type ResponseTemplateCallback = (response: Requests.HandlerResponse) => { /** Headers to send. */ headers: Record<string, any>; /** HTTP status code to use. */ code: number; /** Serialized body content. */ content: string | Buffer; }; /** * Abstract logger interface combining various log levels. * Generic T is the logging function type signature. */ type AbstractLogger<T = (...args: any[]) => any> = ({ log: T; } | { info: T; } | { debug: T; }) & ({ warn: T; } | { warning: T; }) & ({ error: T; } | { exception: T; } | { fail: T; }); } export type RequestMeta = Partial<Internal.Route.RequestMetadataDescriptor>; export { Internal };