import type { IncomingMessage, ServerResponse, Server } from 'node:http'; import type { AddressInfo } from 'node:net'; import type { ParsedUrlQuery } from 'node:querystring'; import type { StormOptions } from '@rayo/storm'; /** Parameters remain URL-encoded. Optional route parameters may be absent. */ export type Params = Record; export interface Request

extends IncomingMessage { ip: string | string[] | undefined; pathname: string; query: ParsedUrlQuery; params: P; } /** Extend this interface, or pass a response subtype to rayo(), for middleware helpers. */ export interface Response extends ServerResponse {} export type Next = (error?: unknown) => unknown; export type Handler = ( req: Req, res: Res, next: Next ) => unknown; export interface RouteMatch { params: Params; /** Route handlers, including middleware from contributing bridges. */ stack: Handler[]; /** Prepared global and route handlers. Treat this shared array as immutable. */ dispatchStack: Handler[]; } export interface Routing { readonly id: string; through(...handlers: Handler[]): this; route(verb: string, path: string, ...handlers: Handler[]): this; fetch(verb: string, path: string): RouteMatch | null; /** Prepare route indexes and middleware stacks. Safe to call repeatedly. */ prepare(): this; } export interface BoundBridge extends Routing { readonly bridgedPath: string; get(...handlers: Handler[]): this; head(...handlers: Handler[]): this; post(...handlers: Handler[]): this; put(...handlers: Handler[]): this; delete(...handlers: Handler[]): this; connect(...handlers: Handler[]): this; options(...handlers: Handler[]): this; trace(...handlers: Handler[]): this; patch(...handlers: Handler[]): this; all(...handlers: Handler[]): this; } export interface Bridge extends Routing { readonly bridgedPath: null; bridge(path: string): BoundBridge; bridge(path?: null): Bridge; get(path: string, ...handlers: Handler[]): this; head(path: string, ...handlers: Handler[]): this; post(path: string, ...handlers: Handler[]): this; put(path: string, ...handlers: Handler[]): this; delete(path: string, ...handlers: Handler[]): this; connect(path: string, ...handlers: Handler[]): this; options(path: string, ...handlers: Handler[]): this; trace(path: string, ...handlers: Handler[]): this; patch(path: string, ...handlers: Handler[]): this; all(path: string, ...handlers: Handler[]): this; } export interface ListenAddress extends AddressInfo { workerPid: number; } export interface RayoOptions { host?: string; port?: number; storm?: StormOptions | null; server?: Server | null; notFound?: Handler | null; onError?: ((error: unknown, req: Req, res: Res, handler: Handler | undefined) => unknown) | null; } export interface Rayo extends Bridge { host: string | undefined; port: number | undefined; server: Server | null; stormOptions: StormOptions | null; notFound: RayoOptions['notFound']; onError: RayoOptions['onError']; /** In a Storm primary process there is no local HTTP server, so this returns null. */ start(callback?: (address: ListenAddress) => void): Server | null; dispatch(req: IncomingMessage, res: ServerResponse): unknown; step(req: Req, res: Res, stack: Handler[], index?: number, error?: unknown, statusCode?: number): unknown; } export default function rayo( options?: RayoOptions ): Rayo;