UNPKG

hono

Version:

Web framework built on Web Standards

443 lines (442 loc) 16.2 kB
import { HonoRequest } from './request'; import type { Result } from './router'; import type { Env, FetchEventLike, H, Input, NotFoundHandler, RouterRoute, TypedResponse } from './types'; import type { RedirectStatusCode, StatusCode } from './utils/http-status'; import type { InvalidJSONValue, IsAny, JSONParsed, JSONValue, SimplifyDeepArray } from './utils/types'; import type { BaseMime } from './utils/mime'; type HeaderRecord = Record<'Content-Type', BaseMime> | Record<ResponseHeader, string | string[]> | Record<string, string | string[]>; /** * Data type can be a string, ArrayBuffer, or ReadableStream. */ export type Data = string | ArrayBuffer | ReadableStream; /** * Interface for the execution context in a web worker or similar environment. */ export interface ExecutionContext { /** * Extends the lifetime of the event callback until the promise is settled. * * @param promise - A promise to wait for. */ waitUntil(promise: Promise<unknown>): void; /** * Allows the event to be passed through to subsequent event listeners. */ passThroughOnException(): void; } /** * Interface for context variable mapping. */ export interface ContextVariableMap { } /** * Interface for context renderer. */ export interface ContextRenderer { } /** * Interface representing a renderer for content. * * @interface DefaultRenderer * @param {string | Promise<string>} content - The content to be rendered, which can be either a string or a Promise resolving to a string. * @returns {Response | Promise<Response>} - The response after rendering the content, which can be either a Response or a Promise resolving to a Response. */ interface DefaultRenderer { (content: string | Promise<string>): Response | Promise<Response>; } /** * Renderer type which can either be a ContextRenderer or DefaultRenderer. */ export type Renderer = ContextRenderer extends Function ? ContextRenderer : DefaultRenderer; /** * Extracts the props for the renderer. */ export type PropsForRenderer = [...Required<Parameters<Renderer>>] extends [unknown, infer Props] ? Props : unknown; export type Layout<T = Record<string, any>> = (props: T) => any; /** * Interface for getting context variables. * * @template E - Environment type. */ interface Get<E extends Env> { <Key extends keyof E['Variables']>(key: Key): E['Variables'][Key]; <Key extends keyof ContextVariableMap>(key: Key): ContextVariableMap[Key]; } /** * Interface for setting context variables. * * @template E - Environment type. */ interface Set<E extends Env> { <Key extends keyof E['Variables']>(key: Key, value: E['Variables'][Key]): void; <Key extends keyof ContextVariableMap>(key: Key, value: ContextVariableMap[Key]): void; } /** * Interface for creating a new response. */ interface NewResponse { (data: Data | null, status?: StatusCode, headers?: HeaderRecord): Response; (data: Data | null, init?: ResponseInit): Response; } /** * Interface for responding with a body. */ interface BodyRespond extends NewResponse { } /** * Interface for responding with text. * * @interface TextRespond * @template T - The type of the text content. * @template U - The type of the status code. * * @param {T} text - The text content to be included in the response. * @param {U} [status] - An optional status code for the response. * @param {HeaderRecord} [headers] - An optional record of headers to include in the response. * * @returns {Response & TypedResponse<T, U, 'text'>} - The response after rendering the text content, typed with the provided text and status code types. */ interface TextRespond { <T extends string, U extends StatusCode = StatusCode>(text: T, status?: U, headers?: HeaderRecord): Response & TypedResponse<T, U, 'text'>; <T extends string, U extends StatusCode = StatusCode>(text: T, init?: ResponseInit): Response & TypedResponse<T, U, 'text'>; } /** * Interface for responding with JSON. * * @interface JSONRespond * @template T - The type of the JSON value or simplified unknown type. * @template U - The type of the status code. * * @param {T} object - The JSON object to be included in the response. * @param {U} [status] - An optional status code for the response. * @param {HeaderRecord} [headers] - An optional record of headers to include in the response. * * @returns {JSONRespondReturn<T, U>} - The response after rendering the JSON object, typed with the provided object and status code types. */ interface JSONRespond { <T extends JSONValue | SimplifyDeepArray<unknown> | InvalidJSONValue, U extends StatusCode = StatusCode>(object: T, status?: U, headers?: HeaderRecord): JSONRespondReturn<T, U>; <T extends JSONValue | SimplifyDeepArray<unknown> | InvalidJSONValue, U extends StatusCode = StatusCode>(object: T, init?: ResponseInit): JSONRespondReturn<T, U>; } /** * @template T - The type of the JSON value or simplified unknown type. * @template U - The type of the status code. * * @returns {Response & TypedResponse<SimplifyDeepArray<T> extends JSONValue ? (JSONValue extends SimplifyDeepArray<T> ? never : JSONParsed<T>) : never, U, 'json'>} - The response after rendering the JSON object, typed with the provided object and status code types. */ type JSONRespondReturn<T extends JSONValue | SimplifyDeepArray<unknown> | InvalidJSONValue, U extends StatusCode> = Response & TypedResponse<SimplifyDeepArray<T> extends JSONValue ? JSONValue extends SimplifyDeepArray<T> ? never : JSONParsed<T> : never, U, 'json'>; /** * Interface representing a function that responds with HTML content. * * @param html - The HTML content to respond with, which can be a string or a Promise that resolves to a string. * @param status - (Optional) The HTTP status code for the response. * @param headers - (Optional) A record of headers to include in the response. * @param init - (Optional) The response initialization object. * * @returns A Response object or a Promise that resolves to a Response object. */ interface HTMLRespond { <T extends string | Promise<string>>(html: T, status?: StatusCode, headers?: HeaderRecord): T extends string ? Response : Promise<Response>; <T extends string | Promise<string>>(html: T, init?: ResponseInit): T extends string ? Response : Promise<Response>; } /** * Options for configuring the context. * * @template E - Environment type. */ type ContextOptions<E extends Env> = { /** * Bindings for the environment. */ env: E['Bindings']; /** * Execution context for the request. */ executionCtx?: FetchEventLike | ExecutionContext | undefined; /** * Handler for not found responses. */ notFoundHandler?: NotFoundHandler<E>; matchResult?: Result<[H, RouterRoute]>; path?: string; }; interface SetHeadersOptions { append?: boolean; } type ResponseHeader = 'Access-Control-Allow-Credentials' | 'Access-Control-Allow-Headers' | 'Access-Control-Allow-Methods' | 'Access-Control-Allow-Origin' | 'Access-Control-Expose-Headers' | 'Access-Control-Max-Age' | 'Age' | 'Allow' | 'Cache-Control' | 'Clear-Site-Data' | 'Content-Disposition' | 'Content-Encoding' | 'Content-Language' | 'Content-Length' | 'Content-Location' | 'Content-Range' | 'Content-Security-Policy' | 'Content-Security-Policy-Report-Only' | 'Content-Type' | 'Cookie' | 'Cross-Origin-Embedder-Policy' | 'Cross-Origin-Opener-Policy' | 'Cross-Origin-Resource-Policy' | 'Date' | 'ETag' | 'Expires' | 'Last-Modified' | 'Location' | 'Permissions-Policy' | 'Pragma' | 'Retry-After' | 'Save-Data' | 'Sec-CH-Prefers-Color-Scheme' | 'Sec-CH-Prefers-Reduced-Motion' | 'Sec-CH-UA' | 'Sec-CH-UA-Arch' | 'Sec-CH-UA-Bitness' | 'Sec-CH-UA-Form-Factor' | 'Sec-CH-UA-Full-Version' | 'Sec-CH-UA-Full-Version-List' | 'Sec-CH-UA-Mobile' | 'Sec-CH-UA-Model' | 'Sec-CH-UA-Platform' | 'Sec-CH-UA-Platform-Version' | 'Sec-CH-UA-WoW64' | 'Sec-Fetch-Dest' | 'Sec-Fetch-Mode' | 'Sec-Fetch-Site' | 'Sec-Fetch-User' | 'Sec-GPC' | 'Server' | 'Server-Timing' | 'Service-Worker-Navigation-Preload' | 'Set-Cookie' | 'Strict-Transport-Security' | 'Timing-Allow-Origin' | 'Trailer' | 'Transfer-Encoding' | 'Upgrade' | 'Vary' | 'WWW-Authenticate' | 'Warning' | 'X-Content-Type-Options' | 'X-DNS-Prefetch-Control' | 'X-Frame-Options' | 'X-Permitted-Cross-Domain-Policies' | 'X-Powered-By' | 'X-Robots-Tag' | 'X-XSS-Protection'; interface SetHeaders { (name: 'Content-Type', value?: BaseMime, options?: SetHeadersOptions): void; (name: ResponseHeader, value?: string, options?: SetHeadersOptions): void; (name: string, value?: string, options?: SetHeadersOptions): void; } type ResponseHeadersInit = [string, string][] | Record<'Content-Type', BaseMime> | Record<ResponseHeader, string> | Record<string, string> | Headers; interface ResponseInit { headers?: ResponseHeadersInit; status?: number; statusText?: string; } export declare const TEXT_PLAIN = "text/plain; charset=UTF-8"; export declare class Context<E extends Env = any, P extends string = any, I extends Input = {}> { #private; /** * `.env` can get bindings (environment variables, secrets, KV namespaces, D1 database, R2 bucket etc.) in Cloudflare Workers. * * @see {@link https://hono.dev/docs/api/context#env} * * @example * ```ts * // Environment object for Cloudflare Workers * app.get('*', async c => { * const counter = c.env.COUNTER * }) * ``` */ env: E['Bindings']; finalized: boolean; /** * `.error` can get the error object from the middleware if the Handler throws an error. * * @see {@link https://hono.dev/docs/api/context#error} * * @example * ```ts * app.use('*', async (c, next) => { * await next() * if (c.error) { * // do something... * } * }) * ``` */ error: Error | undefined; /** * Creates an instance of the Context class. * * @param req - The Request object. * @param options - Optional configuration options for the context. */ constructor(req: Request, options?: ContextOptions<E>); /** * `.req` is the instance of {@link HonoRequest}. */ get req(): HonoRequest<P, I['out']>; /** * @see {@link https://hono.dev/docs/api/context#event} * The FetchEvent associated with the current request. * * @throws Will throw an error if the context does not have a FetchEvent. */ get event(): FetchEventLike; /** * @see {@link https://hono.dev/docs/api/context#executionctx} * The ExecutionContext associated with the current request. * * @throws Will throw an error if the context does not have an ExecutionContext. */ get executionCtx(): ExecutionContext; /** * @see {@link https://hono.dev/docs/api/context#res} * The Response object for the current request. */ get res(): Response; /** * Sets the Response object for the current request. * * @param _res - The Response object to set. */ set res(_res: Response | undefined); /** * `.render()` can create a response within a layout. * * @see {@link https://hono.dev/docs/api/context#render-setrenderer} * * @example * ```ts * app.get('/', (c) => { * return c.render('Hello!') * }) * ``` */ render: Renderer; /** * Sets the layout for the response. * * @param layout - The layout to set. * @returns The layout function. */ setLayout: (layout: Layout<PropsForRenderer & { Layout: Layout; }>) => Layout<PropsForRenderer & { Layout: Layout; }>; /** * Gets the current layout for the response. * * @returns The current layout function. */ getLayout: () => Layout<PropsForRenderer & { Layout: Layout; }> | undefined; /** * `.setRenderer()` can set the layout in the custom middleware. * * @see {@link https://hono.dev/docs/api/context#render-setrenderer} * * @example * ```tsx * app.use('*', async (c, next) => { * c.setRenderer((content) => { * return c.html( * <html> * <body> * <p>{content}</p> * </body> * </html> * ) * }) * await next() * }) * ``` */ setRenderer: (renderer: Renderer) => void; /** * `.header()` can set headers. * * @see {@link https://hono.dev/docs/api/context#body} * * @example * ```ts * app.get('/welcome', (c) => { * // Set headers * c.header('X-Message', 'Hello!') * c.header('Content-Type', 'text/plain') * * return c.body('Thank you for coming') * }) * ``` */ header: SetHeaders; status: (status: StatusCode) => void; /** * `.set()` can set the value specified by the key. * * @see {@link https://hono.dev/docs/api/context#set-get} * * @example * ```ts * app.use('*', async (c, next) => { * c.set('message', 'Hono is cool!!') * await next() * }) * ``` */ set: Set<IsAny<E> extends true ? { Variables: ContextVariableMap & Record<string, any>; } : E>; /** * `.get()` can use the value specified by the key. * * @see {@link https://hono.dev/docs/api/context#set-get} * * @example * ```ts * app.get('/', (c) => { * const message = c.get('message') * return c.text(`The message is "${message}"`) * }) * ``` */ get: Get<IsAny<E> extends true ? { Variables: ContextVariableMap & Record<string, any>; } : E>; /** * `.var` can access the value of a variable. * * @see {@link https://hono.dev/docs/api/context#var} * * @example * ```ts * const result = c.var.client.oneMethod() * ``` */ get var(): Readonly<ContextVariableMap & (IsAny<E['Variables']> extends true ? Record<string, any> : E['Variables'])>; newResponse: NewResponse; /** * `.body()` can return the HTTP response. * You can set headers with `.header()` and set HTTP status code with `.status`. * This can also be set in `.text()`, `.json()` and so on. * * @see {@link https://hono.dev/docs/api/context#body} * * @example * ```ts * app.get('/welcome', (c) => { * // Set headers * c.header('X-Message', 'Hello!') * c.header('Content-Type', 'text/plain') * // Set HTTP status code * c.status(201) * * // Return the response body * return c.body('Thank you for coming') * }) * ``` */ body: BodyRespond; /** * `.text()` can render text as `Content-Type:text/plain`. * * @see {@link https://hono.dev/docs/api/context#text} * * @example * ```ts * app.get('/say', (c) => { * return c.text('Hello!') * }) * ``` */ text: TextRespond; /** * `.json()` can render JSON as `Content-Type:application/json`. * * @see {@link https://hono.dev/docs/api/context#json} * * @example * ```ts * app.get('/api', (c) => { * return c.json({ message: 'Hello!' }) * }) * ``` */ json: JSONRespond; html: HTMLRespond; /** * `.redirect()` can Redirect, default status code is 302. * * @see {@link https://hono.dev/docs/api/context#redirect} * * @example * ```ts * app.get('/redirect', (c) => { * return c.redirect('/') * }) * app.get('/redirect-permanently', (c) => { * return c.redirect('/', 301) * }) * ``` */ redirect: <T extends RedirectStatusCode = 302>(location: string, status?: T | undefined) => Response & TypedResponse<undefined, T, "redirect">; /** * `.notFound()` can return the Not Found Response. * * @see {@link https://hono.dev/docs/api/context#notfound} * * @example * ```ts * app.get('/notfound', (c) => { * return c.notFound() * }) * ``` */ notFound: () => Response | Promise<Response>; } export {};