/** * Contains the core concept of oak, the middleware application. Typical usage * is the creation of an application instance, registration of middleware, and * then starting to listen for requests. * * # Example * * ```ts * import { Application } from "jsr:@oak/oak@14/application"; * * const app = new Application(); * app.use((ctx) => { * ctx.response.body = "hello world!"; * }); * * app.listen({ port: 8080 }); * ``` * * @module */ import * as dntShim from "./_dnt.shims.js"; import { Context } from "./context.js"; import { KeyStack } from "./deps.js"; import { type MiddlewareOrMiddlewareObject } from "./middleware.js"; import { Key, Listener, NetAddr, ServerConstructor, ServerRequest } from "./types.js"; /** Base interface for application listening options. */ export interface ListenOptionsBase { /** The port to listen on. If not specified, defaults to `0`, which allows the * operating system to determine the value. */ port?: number; /** A literal IP address or host name that can be resolved to an IP address. * If not specified, defaults to `0.0.0.0`. * * __Note about `0.0.0.0`__ While listening `0.0.0.0` works on all platforms, * the browsers on Windows don't work with the address `0.0.0.0`. * You should show the message like `server running on localhost:8080` instead of * `server running on 0.0.0.0:8080` if your program supports Windows. */ hostname?: string; secure?: false; /** An optional abort signal which can be used to close the listener. */ signal?: AbortSignal; } /** Interface options when listening on TLS. */ export interface ListenOptionsTls extends dntShim.Deno.ListenTlsOptions { /** Application-Layer Protocol Negotiation (ALPN) protocols to announce to * the client. If not specified, no ALPN extension will be included in the * TLS handshake. * * **NOTE** this is part of the native HTTP server in Deno 1.9 or later, * which requires the `--unstable` flag to be available. */ alpnProtocols?: string[]; secure: true; /** An optional abort signal which can be used to close the listener. */ signal?: AbortSignal; } interface HandleMethod { /** Handle an individual server request, returning the server response. This * is similar to `.listen()`, but opening the connection and retrieving * requests are not the responsibility of the application. If the generated * context gets set to not to respond, then the method resolves with * `undefined`, otherwise it resolves with a DOM `Response` object. */ (request: dntShim.Request, remoteAddr?: NetAddr, secure?: boolean): Promise; } interface CloudflareExecutionContext { waitUntil(promise: Promise): void; passThroughOnException(): void; } interface CloudflareFetchHandler = Record> { /** A method that is compatible with the Cloudflare Worker * [Fetch Handler](https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/) * and can be exported to handle Cloudflare Worker fetch requests. * * # Example * * ```ts * import { Application } from "@oak/oak"; * * const app = new Application(); * app.use((ctx) => { * ctx.response.body = "hello world!"; * }); * * export default { fetch: app.fetch }; * ``` */ (request: dntShim.Request, env: Env, ctx: CloudflareExecutionContext): Promise; } /** Options which can be specified when listening. */ export type ListenOptions = ListenOptionsTls | ListenOptionsBase; interface ApplicationCloseEventListener { (evt: ApplicationCloseEvent): void | Promise; } interface ApplicationCloseEventListenerObject { handleEvent(evt: ApplicationCloseEvent): void | Promise; } type ApplicationCloseEventListenerOrEventListenerObject = ApplicationCloseEventListener | ApplicationCloseEventListenerObject; interface ApplicationErrorEventListener { (evt: ApplicationErrorEvent): void | Promise; } interface ApplicationErrorEventListenerObject { handleEvent(evt: ApplicationErrorEvent): void | Promise; } interface ApplicationErrorEventInit extends ErrorEventInit { context?: Context; } type ApplicationErrorEventListenerOrEventListenerObject = ApplicationErrorEventListener | ApplicationErrorEventListenerObject; interface ApplicationListenEventListener { (evt: ApplicationListenEvent): void | Promise; } interface ApplicationListenEventListenerObject { handleEvent(evt: ApplicationListenEvent): void | Promise; } interface ApplicationListenEventInit extends EventInit { hostname: string; listener: Listener; port: number; secure: boolean; serverType: "native" | "node" | "bun" | "custom"; } type ApplicationListenEventListenerOrEventListenerObject = ApplicationListenEventListener | ApplicationListenEventListenerObject; /** Available options that are used when creating a new instance of * {@linkcode Application}. */ export interface ApplicationOptions { /** Determine how when creating a new context, the state from the application * should be applied. A value of `"clone"` will set the state as a clone of * the app state. Any non-cloneable or non-enumerable properties will not be * copied. A value of `"prototype"` means that the application's state will be * used as the prototype of the the context's state, meaning shallow * properties on the context's state will not be reflected in the * application's state. A value of `"alias"` means that application's `.state` * and the context's `.state` will be a reference to the same object. A value * of `"empty"` will initialize the context's `.state` with an empty object. * * The default value is `"clone"`. */ contextState?: "clone" | "prototype" | "alias" | "empty"; /** An optional replacer function to be used when serializing a JSON * response. The replacer will be used with `JSON.stringify()` to encode any * response bodies that need to be converted before sending the response. * * This is intended to allow responses to contain bigints and circular * references and encoding other values which JSON does not support directly. * * This can be used in conjunction with `jsonBodyReviver` to handle decoding * of request bodies if the same semantics are used for client requests. * * If more detailed or conditional usage is required, then serialization * should be implemented directly in middleware. */ jsonBodyReplacer?: (key: string, value: unknown, context: Context) => unknown; /** An optional reviver function to be used when parsing a JSON request. The * reviver will be used with `JSON.parse()` to decode any response bodies that * are being converted as JSON. * * This is intended to allow requests to deserialize to bigints, circular * references, or other values which JSON does not support directly. * * This can be used in conjunction with `jsonBodyReplacer` to handle decoding * of response bodies if the same semantics are used for responses. * * If more detailed or conditional usage is required, then deserialization * should be implemented directly in the middleware. */ jsonBodyReviver?: (key: string, value: unknown, context: Context) => unknown; /** An initial set of keys (or instance of {@linkcode KeyStack}) to be used for signing * cookies produced by the application. */ keys?: KeyStack | Key[]; /** If `true`, any errors handled by the application will be logged to the * stderr. If `false` nothing will be logged. The default is `true`. * * All errors are available as events on the application of type `"error"` and * can be accessed for custom logging/application management via adding an * event listener to the application: * * ```ts * const app = new Application({ logErrors: false }); * app.addEventListener("error", (evt) => { * // evt.error will contain what error was thrown * }); * ``` */ logErrors?: boolean; /** If set to `true`, proxy headers will be trusted when processing requests. * This defaults to `false`. */ proxy?: boolean; /** A server constructor to use instead of the default server for receiving * requests. * * Generally this is only used for testing. */ serverConstructor?: ServerConstructor; /** The initial state object for the application, of which the type can be * used to infer the type of the state for both the application and any of the * application's context. */ state?: S; } /** The base type of state which is associated with an application or * context. */ export type State = Record; /** An event that occurs when the application closes. */ export declare class ApplicationCloseEvent extends Event { constructor(eventInitDict: EventInit); } /** An event that occurs when an application error occurs. * * When the error occurs related to the handling of a request, the `.context` * property will be populated. */ export declare class ApplicationErrorEvent extends ErrorEvent { context?: Context; constructor(eventInitDict: ApplicationErrorEventInit); } /** * An event that occurs when the application starts listening for requests. */ export declare class ApplicationListenEvent extends Event { hostname: string; listener: Listener; port: number; secure: boolean; serverType: "native" | "node" | "bun" | "custom"; constructor(eventInitDict: ApplicationListenEventInit); } /** A class which registers middleware (via `.use()`) and then processes * inbound requests against that middleware (via `.listen()`). * * The `context.state` can be typed via passing a generic argument when * constructing an instance of `Application`. It can also be inferred by setting * the {@linkcode ApplicationOptions.state} option when constructing the * application. * * ### Basic example * * ```ts * import { Application } from "https://deno.land/x/oak/mod.ts"; * * const app = new Application(); * * app.use((ctx, next) => { * // called on each request with the context (`ctx`) of the request, * // response, and other data. * // `next()` is use to modify the flow control of the middleware stack. * }); * * app.listen({ port: 8080 }); * ``` * * @template AS the type of the application state which extends * {@linkcode State} and defaults to a simple string record. */ export declare class Application> extends EventTarget { #private; /** A set of keys, or an instance of `KeyStack` which will be used to sign * cookies read and set by the application to avoid tampering with the * cookies. */ get keys(): KeyStack | Key[] | undefined; set keys(keys: KeyStack | Key[] | undefined); /** If `true`, proxy headers will be trusted when processing requests. This * defaults to `false`. */ proxy: boolean; /** Generic state of the application, which can be specified by passing the * generic argument when constructing: * * const app = new Application<{ foo: string }>(); * * Or can be contextually inferred based on setting an initial state object: * * const app = new Application({ state: { foo: "bar" } }); * * When a new context is created, the application's state is cloned and the * state is unique to that request/response. Changes can be made to the * application state that will be shared with all contexts. */ state: AS; constructor(options?: ApplicationOptions); /** Add an event listener for a `"close"` event which occurs when the * application is closed and no longer listening or handling requests. */ addEventListener(type: "close", listener: ApplicationCloseEventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions): void; /** Add an event listener for an `"error"` event which occurs when an * un-caught error occurs when processing the middleware or during processing * of the response. */ addEventListener(type: "error", listener: ApplicationErrorEventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions): void; /** Add an event listener for a `"listen"` event which occurs when the server * has successfully opened but before any requests start being processed. */ addEventListener(type: "listen", listener: ApplicationListenEventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions): void; /** A method that is compatible with the Cloudflare Worker * [Fetch Handler](https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/) * and can be exported to handle Cloudflare Worker fetch requests. * * # Example * * ```ts * import { Application } from "@oak/oak"; * * const app = new Application(); * app.use((ctx) => { * ctx.response.body = "hello world!"; * }); * * export default { fetch: app.fetch }; * ``` */ fetch: CloudflareFetchHandler; /** Handle an individual server request, returning the server response. This * is similar to `.listen()`, but opening the connection and retrieving * requests are not the responsibility of the application. If the generated * context gets set to not to respond, then the method resolves with * `undefined`, otherwise it resolves with a request that is compatible with * `std/http/server`. */ handle: HandleMethod; /** Start listening for requests, processing registered middleware on each * request. If the options `.secure` is undefined or `false`, the listening * will be over HTTP. If the options `.secure` property is `true`, a * `.certFile` and a `.keyFile` property need to be supplied and requests * will be processed over HTTPS. */ listen(addr: string): Promise; /** Start listening for requests, processing registered middleware on each * request. If the options `.secure` is undefined or `false`, the listening * will be over HTTP. If the options `.secure` property is `true`, a * `.certFile` and a `.keyFile` property need to be supplied and requests * will be processed over HTTPS. * * Omitting options will default to `{ port: 0 }` which allows the operating * system to select the port. */ listen(options?: ListenOptions): Promise; /** Register middleware to be used with the application. Middleware will * be processed in the order it is added, but middleware can control the flow * of execution via the use of the `next()` function that the middleware * function will be called with. The `context` object provides information * about the current state of the application. * * Basic usage: * * ```ts * const import { Application } from "https://deno.land/x/oak/mod.ts"; * * const app = new Application(); * * app.use((ctx, next) => { * ctx.request; // contains request information * ctx.response; // setups up information to use in the response; * await next(); // manages the flow control of the middleware execution * }); * * await app.listen({ port: 80 }); * ``` */ use(middleware: MiddlewareOrMiddlewareObject>, ...middlewares: MiddlewareOrMiddlewareObject>[]): Application; } export {};