UNPKG

bunshine

Version:

A Bun HTTP & WebSocket server that is a little ray of sunshine.

312 lines (308 loc) 14.8 kB
// Generated by dts-bundle-generator v9.5.1 import { Server, ServerWebSocket, ServerWebSocketSendStatus, TLSServeOptions, ZlibCompressionOptions } from 'bun'; import { LRUCache } from 'lru-cache'; import { BrotliOptions } from 'node:zlib'; import { RequireAtLeastOne, TypedArray } from 'type-fest'; export type Registration<T> = { matcher: (subject: string) => null | Record<string, string>; pattern: string; regex: RegExp; methodFilter: null | ((subject: string) => boolean); target: T; }; export type Result<T> = Array<[ T, Record<string, string> ]>; declare class RouteMatcher<Target extends any> { registered: Registration<Target>[]; match(method: string, subject: string, fallbacks?: Target[]): Result<Target>; add(method: string, pattern: string | RegExp, target: Target): this; detectPotentialDos(detector: any, config?: any): void; } declare class MatcherWithCache<Target = any> extends RouteMatcher<Target> { cache: LRUCache<string, any>; constructor(size?: number); match(method: string, subject: string, fallbacks?: Target[]): any; } declare class SocketContext<UpgradeShape = any, ParamsShape = Record<string, any>> { ws?: ServerWebSocket<WsDataShape<UpgradeShape, ParamsShape>>; server: Server; url: URL; params: ParamsShape; data: UpgradeShape; type: SocketEventName; constructor(server: Server, url: URL, params: ParamsShape, data: UpgradeShape); get remoteAddress(): string; get readyState(): Bun.WebSocketReadyState; set binaryType(type: "nodebuffer" | "arraybuffer" | "uint8array"); get binaryType(): "nodebuffer" | "arraybuffer" | "uint8array" | undefined; send(message: any, compress?: boolean): number; close(status?: number, reason?: string): this; terminate(): this; subscribe(topic: string): this; unsubscribe(topic: string): this; isSubscribed(topic: string): boolean; cork(callback: (ws: ServerWebSocket<WsDataShape<UpgradeShape, ParamsShape>>) => WsDataShape<UpgradeShape, ParamsShape>): WsDataShape<UpgradeShape, ParamsShape>; publish(topic: string, message: any, compress?: boolean): number; ping(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; pong(data?: string | Bun.BufferSource): ServerWebSocketSendStatus; } export type SocketEventName = "upgrade" | "open" | "message" | "close" | "drain" | "ping" | "pong" | "error"; declare class SocketMessage<T extends SocketEventName> { readonly type: T; private readonly _rawMessage; constructor(type: T, rawMessage: string | Buffer); raw(): string | Buffer<ArrayBufferLike>; text(encoding?: BufferEncoding): string; toString(encoding?: BufferEncoding): string; buffer(): Buffer<ArrayBufferLike>; arrayBuffer(): ArrayBufferLike; readableStream(chunkSize?: number): ReadableStream<Uint8Array<ArrayBufferLike>>; json(): any; } export type WsDataShape<U = any, P = Record<string, any>> = { sc: SocketContext<U, P>; }; export type SocketUpgradeHandler<U, P extends Record<string, any> = Record<string, any>> = (context: Context<P>, next: NextFunction) => U | Promise<U>; export type SocketPlainHandler<U, P> = (context: SocketContext<U, P>) => void; export type SocketMessageHandler<U, P, T extends SocketEventType> = (context: SocketContext<U, P>, message: SocketMessage<T>) => void; export type SocketErrorHandler<U, P> = (context: SocketContext<U, P>, error: Error) => void; export type SocketCloseHandler<U, P> = (context: SocketContext<U, P>, status: number, reason: string) => void; export type BunshineHandlers<U, P extends Record<string, string> = Record<string, string>> = RequireAtLeastOne<{ upgrade: SocketUpgradeHandler<U, P>; error: SocketErrorHandler<U, P>; open: SocketPlainHandler<U, P>; message: SocketMessageHandler<U, P, "message">; close: SocketCloseHandler<U, P>; drain: SocketPlainHandler<U, P>; ping: SocketMessageHandler<U, P, "ping">; pong: SocketMessageHandler<U, P, "pong">; }>; export type BunHandlers = { open: (ws: ServerWebSocket<WsDataShape>) => void; message: (ws: ServerWebSocket<WsDataShape>, data: any) => void; close: (ws: ServerWebSocket<WsDataShape>, code: number, reason: string) => void; drain: (ws: ServerWebSocket<WsDataShape>) => void; ping: (ws: ServerWebSocket<WsDataShape>, data: any) => void; pong: (ws: ServerWebSocket<WsDataShape>, data: any) => void; }; export type SocketEventType = "open" | "message" | "close" | "drain" | "ping" | "pong"; export declare class SocketRouter { httpRouter: HttpRouter; routeMatcher: RouteMatcher<BunshineHandlers<any>>; handlers: BunHandlers; constructor(router: HttpRouter); at: <P extends Record<string, string> = Record<string, string>, U = any>(path: string, handlers: BunshineHandlers<U, P>) => this; private _fallbackError; private _createHandler; } export type NextFunction = () => Promise<Response>; export type SingleHandler<ParamsShape extends Record<string, string> = Record<string, string>> = (context: Context<ParamsShape>, next: NextFunction) => Response | void | Promise<Response | void>; export type Handler<ParamsShape extends Record<string, string> = Record<string, string>> = SingleHandler<ParamsShape> | Handler<ParamsShape>[]; export type Middleware<ParamsShape extends Record<string, string> = Record<string, string>> = SingleHandler<ParamsShape> | Handler<ParamsShape>[]; export type ListenOptions = Omit<TLSServeOptions, "fetch" | "websocket"> | number; export type HttpMethods = "ALL" | "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS" | "TRACE"; export type HttpRouterOptions = { cacheSize?: number; }; export type EmitUrlOptions = { verbose?: boolean; to?: (message: string) => void; date?: boolean; }; export declare class HttpRouter { version: string; locals: Record<string, any>; server: Server | undefined; routeMatcher: MatcherWithCache<SingleHandler>; _wsRouter?: SocketRouter; onNotFound: (...handlers: Handler[]) => HttpRouter; onError: (...handlers: Handler[]) => HttpRouter; private _on404Handlers; private _on500Handlers; constructor(options?: HttpRouterOptions); listen(portOrOptions?: ListenOptions): Server; emitUrl({ verbose, to, date, }?: EmitUrlOptions): void; getExport(options?: Omit<TLSServeOptions, "fetch" | "websocket">): TLSServeOptions; get socket(): SocketRouter; on<ParamsShape extends Record<string, string> = Record<string, string>>(verbOrVerbs: HttpMethods | HttpMethods[], path: string | RegExp, ...handlers: Handler<ParamsShape>[]): this; all<ParamsShape extends Record<string, string> = Record<string, string>>(path: string | RegExp, ...handlers: Handler<ParamsShape>[]): this; get<ParamsShape extends Record<string, string> = Record<string, string>>(path: string | RegExp, ...handlers: Handler<ParamsShape>[]): this; put<ParamsShape extends Record<string, string> = Record<string, string>>(path: string | RegExp, ...handlers: Handler<ParamsShape>[]): this; head<ParamsShape extends Record<string, string> = Record<string, string>>(path: string | RegExp, ...handlers: Handler<ParamsShape>[]): this; post<ParamsShape extends Record<string, string> = Record<string, string>>(path: string | RegExp, ...handlers: Handler<ParamsShape>[]): this; patch<ParamsShape extends Record<string, string> = Record<string, string>>(path: string | RegExp, ...handlers: Handler<ParamsShape>[]): this; trace<ParamsShape extends Record<string, string> = Record<string, string>>(path: string | RegExp, ...handlers: Handler<ParamsShape>[]): this; delete<ParamsShape extends Record<string, string> = Record<string, string>>(path: string | RegExp, ...handlers: Handler<ParamsShape>[]): this; options<ParamsShape extends Record<string, string> = Record<string, string>>(path: string | RegExp, ...handlers: Handler<ParamsShape>[]): this; headGet<ParamsShape extends Record<string, string> = Record<string, string>>(path: string | RegExp, ...handlers: Handler<ParamsShape>[]): this; use: (...handlers: Handler[]) => this; on404: (...handlers: Handler[]) => this; on500: (...handlers: Handler[]) => this; fetch: (request: Request, server: Server) => Promise<Response>; } export type FileLike = string | Blob | Uint8Array | ArrayBuffer; export type FileResponseOptions = { chunkSize?: number; disposition?: "inline" | "attachment" | "form-data"; acceptRanges?: boolean; sendLastModified?: boolean; headers?: HeadersInit; }; export type SseSend = (eventName: string, data?: string | object, id?: string, retry?: number) => void | Promise<void>; export type SseClose = () => void | Promise<void>; export type SseSetupFunction = (send: SseSend, close: SseClose) => void | (() => void); export declare class Context<ParamsShape extends Record<string, string> = Record<string, string>> { /** The raw request object */ request: Request; /** Alias for `request` */ req: Request; /** The Bun server instance */ server: Server; /** The HttpRouter instance */ app: HttpRouter; /** The request params from URL placeholders */ params: ParamsShape; /** A place to persist data between handlers for the duration of the request */ locals: Record<string, any>; /** A URL object constructed with `new URL(request.url)` */ url: URL; /** The date the request was received */ date: Date; /** The milliseconds between server start and this request, as float (from performance.now()) */ now: number; /** If an error has been thrown, the error Object */ error: Error | null; constructor(request: Request, server: Server, app: HttpRouter); /** Get the IP address info of the client */ get ip(): { address: string; family: string; port: number; } | null; /** A shorthand for `new Response(text, { headers: { 'Content-type': 'text/plain' } })` */ text: (text: string, init?: ResponseInit) => Response; /** A shorthand for `new Response(js, { headers: { 'Content-type': 'text/javascript' } })` */ js: (js: string, init?: ResponseInit) => Response; /** A shorthand for `new Response(html, { headers: { 'Content-type': 'text/html' } })` */ html: (html: string, init?: ResponseInit) => Response; /** A shorthand for `new Response(html, { headers: { 'Content-type': 'text/css' } })` */ css: (css: string, init?: ResponseInit) => Response; /** A shorthand for `new Response(xml, { headers: { 'Content-type': 'text/xml' } })` */ xml: (xml: string, init?: ResponseInit) => Response; /** A shorthand for `new Response(JSON.stringify(data), { headers: { 'Content-type': 'application/json' } })` */ json: (data: any, init?: ResponseInit) => Response; /** A shorthand for `new Response(null, { headers: { Location: url }, status: 301 })` */ redirect: (url: string, status?: number) => Response; /** A shorthand for `new Response(bunFile, fileHeaders)` plus range features */ file: (pathOrData: FileLike, fileOptions?: FileResponseOptions) => Promise<Response>; /** A shorthand for `new Response({ headers: { 'Content-type': 'text/event-stream' } })` */ sse: (setup: SseSetupFunction, init?: ResponseInit) => Response; } export type ApplyHandlerIfArgs = { requestCondition?: (c: Context) => Promise<boolean> | boolean; responseCondition?: (c: Context, resp: Response) => Promise<boolean> | boolean; handler: Handler; }; export declare function applyHandlerIf(conditions: ApplyHandlerIfArgs): Middleware; export type CompressionOptions = { prefer: "br" | "gzip" | "none"; br: BrotliOptions; gzip: ZlibCompressionOptions; minSize: number; maxSize: number; exceptWhen: (context: Context, response: Response) => boolean | Promise<boolean>; }; export declare const compressionDefaults: { prefer: "gzip"; br: BrotliOptions; gzip: ZlibCompressionOptions; minSize: number; maxSize: number; exceptWhen: () => boolean; }; export declare function compression(options?: Partial<CompressionOptions>): Middleware; export type CorsOptions = { origin?: string | RegExp | Array<string | RegExp> | boolean | ((incomingOrigin: string, context: Context) => string | string[] | boolean | undefined | null); allowMethods?: string[]; allowHeaders?: string[]; maxAge?: number; credentials?: boolean; exposeHeaders?: string[]; exceptWhen?: (context: Context, response: Response) => boolean | Promise<boolean>; }; export declare const corsDefaults: { origin: string; allowMethods: string[]; maxAge: undefined; credentials: undefined; allowHeaders: never[]; exposeHeaders: never[]; exceptWhen: () => boolean; }; export declare function cors(options?: CorsOptions): Middleware; export type LoggerOptions = { writer?: (msg: string) => void; exceptWhen?: (context: Context, response: Response | null) => boolean | Promise<boolean>; }; export declare function devLogger(options?: LoggerOptions): Middleware; export type EtagHashCalculator = (context: Context, response: Response) => Promise<{ buffer: ArrayBuffer | TypedArray | Buffer; hash: string; }>; export type EtagOptions = { calculator?: EtagHashCalculator; maxSize?: number; exceptWhen?: (context: Context, response: Response) => boolean; }; export declare function etags({ calculator, maxSize, // 2GB exceptWhen, }?: EtagOptions): Middleware; export declare function defaultEtagsCalculator(_: Context, resp: Response): Promise<{ buffer: ArrayBuffer; hash: string; }>; export type HeaderValue = string | ((c: Context, resp: Response) => string | null | Promise<string | null>); export type HeaderValues = Record<string, HeaderValue>; export type HeaderCondition = (c: Context, resp: Response) => boolean | Promise<boolean>; export declare function headers(headers: HeaderValues, condition?: HeaderCondition): Middleware; export declare function performanceHeader(headerName?: string): Middleware; export declare function prodLogger(options?: LoggerOptions): Middleware; export type ServeFilesOptions = { acceptRanges?: boolean; dotfiles?: "allow" | "deny" | "ignore"; extensions?: string[]; fallthrough?: boolean; immutable?: boolean; index?: string[]; lastModified?: boolean; maxAge?: number | string; exceptWhen?: (context: Context, response: Response | null) => boolean; }; export declare function serveFiles(directory: string, { acceptRanges, dotfiles, extensions, fallthrough, immutable, index, lastModified, maxAge, exceptWhen, }?: ServeFilesOptions): Middleware; export declare function trailingSlashes(mode: "add" | "remove"): Middleware; export function ms(expression: string | number): number; export type RangeInformation = { rangeHeader?: string | null | false; totalFileSize: number; defaultChunkSize?: number; }; export function parseRangeHeader({ rangeHeader, totalFileSize, defaultChunkSize, }: RangeInformation): { slice: null; contentLength: number; status: number; } | { slice: null; contentLength: null; status: number; } | { slice: { start: number; end: number; }; contentLength: number; status: number; }; export type Factory = (body: string, init?: ResponseInit) => Response; export function factory(contentType: string): Factory; export {};