Reference

alien-middleware

Functions

chain

Create a middleware chain from an existing middleware or chain.

export function chain<T extends AnyMiddleware | null | undefined>(middleware: T): T extends AnyMiddlewareChain ? T : T extends Middleware ? RequestHandler<ApplyFirstMiddleware<T>> : never;

🔍 chain on GitHub

createContext

Create an alien-middleware request context from a Web Request.

export function createContext<TRuntime = unknown, TEnv extends object = any>({ host, request, }: CreateContextOptions<TRuntime>): RequestContext<TEnv, {}, TRuntime>;

🔍 createContext on GitHub

filterRuntime

Continue only when context.host.runtime?.name matches the given runtime name.

export function filterRuntime<TRuntime extends {
    name: string;
}>(name: TRuntime['name']): (ctx: RequestContext) => {
    runtime: TRuntime;
};

🔍 filterRuntime on GitHub

toFetchHandler

Adapt a request handler into a fetch-compatible (request) => response function.

export function toFetchHandler<T extends MiddlewareTypes, TRequest extends Request = Request>(handler: RequestHandler<T>, options?: ToFetchHandlerOptions<T['runtime'], TRequest>): FetchHandler<TRequest>;

🔍 toFetchHandler on GitHub

Classes

MiddlewareChain

Immutable list of request middleware with type metadata for inference.

export class MiddlewareChain<T extends MiddlewareTypes = any> {
    /** This property won't exist at runtime. It contains type information for inference purposes. */
    $MiddlewareChain: T;
    /** The number of parameters when called as a function. */
    readonly length: 1;
    protected [kRequestChain]: RequestMiddleware[];
    /** Number of request middleware functions in this chain. */
    get middlewareCount(): number;
    /**
     * Add a request middleware to the end of the chain.
     *
     * If a middleware chain is given, its middlewares will be executed after any
     * existing middlewares in this chain.
     *
     * @returns a new `MiddlewareChain` instance
     */
    use<const TMiddleware extends ExtractMiddleware<this>>(middleware: TMiddleware | null): RequestHandler<ApplyMiddleware<this, TMiddleware>>;
    /**
     * Create a middleware function that encapsulates this middleware chain, so
     * any modifications it makes to the request context are not leaked.
     */
    isolate(): (ctx: IsolatedContext<this>) => Awaitable<Response | void>;
    /**
     * @internal You should not need to call this method, unless you want a
     * `RequestHandler` type from an empty middleware chain. If your middleware
     * chain is **not** empty, you won't need this.
     */
    toHandler<T2 extends MiddlewareTypes = T>(): RequestHandler<T2>;
}

🔍 MiddlewareChain on GitHub

Constants

kRequestChain

Symbol key for a chain's internal request middleware list.

const kRequestChain: unique symbol;

🔍 kRequestChain on GitHub

Types

AnyMiddleware

Any request middleware function or middleware chain.

export type AnyMiddleware = Middleware | AnyMiddlewareChain;

🔍 AnyMiddleware on GitHub

AnyMiddlewareChain

A value with middleware-chain type metadata.

export type AnyMiddlewareChain<T extends AnyMiddlewareTypes = AnyMiddlewareTypes> = {
    $MiddlewareChain: T;
};

🔍 AnyMiddlewareChain on GitHub

AnyMiddlewareTypes

Type metadata for any middleware chain.

type AnyMiddlewareTypes = {
    initial: {
        env: any;
        properties: any;
    };
    current: {
        env: any;
        properties: any;
    };
    runtime: any;
};

🔍 AnyMiddlewareTypes on GitHub

ApplyFirstMiddleware

Convert a Middleware type into a MiddlewareTypes type.

type ApplyFirstMiddleware<T extends AnyMiddleware> = T extends AnyMiddlewareChain<infer TInternal> ? TInternal : ApplyMiddleware<EmptyMiddlewareChain<MiddlewareRuntime<T>>, T>;

🔍 ApplyFirstMiddleware on GitHub

ApplyMiddleware

This applies a middleware to a chain. If the type TSecond is itself a chain, it's treated as a nested chain, which won't leak its plugins into the parent chain.

The TFirst type is allowed to be never, which results in the middleware's output types being used as the request handler's input types.

export type ApplyMiddleware<TFirst extends AnyMiddlewareChain, TSecond extends AnyMiddleware> = ApplyMiddlewareOutputs<TFirst, TSecond> extends infer TCurrent extends MiddlewareTypes['current'] & {
    runtime: unknown;
} ? {
    initial: CastNever<Inputs<TFirst>, MiddlewareInputs<TSecond>>;
    current: Pick<TCurrent, 'env' | 'properties'>;
    runtime: TCurrent['runtime'];
} : never;

🔍 ApplyMiddleware on GitHub

ApplyMiddlewareOutputs

Outputs produced after appending one middleware or chain to another.

type ApplyMiddlewareOutputs<TFirst extends AnyMiddlewareChain, TSecond extends AnyMiddleware> = TSecond extends AnyMiddlewareChain ? {
    env: Merge<Env<TFirst>, Env<TSecond>>;
    properties: Merge<Properties<TFirst>, Properties<TSecond>>;
    runtime: Runtime<TSecond>;
} : TSecond extends (...args: any[]) => Awaitable<infer TResult> ? ApplyMiddlewareResult<TFirst, Exclude<TResult, Response>> : Current<TFirst> & {
    runtime: Runtime<TFirst>;
};

🔍 ApplyMiddlewareOutputs on GitHub

ApplyMiddlewareResult

Merge a request plugin into a middleware chain.

type ApplyMiddlewareResult<TParent extends AnyMiddlewareChain, TResult> = Eval<{
    env: Merge<Env<TParent>, TResult extends {
        env: infer TEnv extends object | undefined;
    } ? TEnv : undefined>;
    properties: Merge<Properties<TParent>, TResult extends RequestPlugin ? Omit<TResult, keyof ReservedProperties> : undefined>;
    runtime: [TResult] extends [never] ? Runtime<TParent> : TResult extends {
        runtime: infer TRuntime;
    } ? TRuntime : Runtime<TParent>;
}>;

🔍 ApplyMiddlewareResult on GitHub

ApplyMiddlewares

Flatten a list of middlewares into a MiddlewareTypes type.

export type ApplyMiddlewares<T extends AnyMiddleware[]> = T extends [
    ...infer TRest extends AnyMiddleware[],
    infer TLast extends AnyMiddleware
] ? ApplyMiddleware<MiddlewareChain<ApplyMiddlewares<TRest>>, TLast> : ApplyFirstMiddleware<T[0]>;

🔍 ApplyMiddlewares on GitHub

Awaitable

A value that may be returned synchronously or through a promise.

type Awaitable<T> = T | Promise<T>;

🔍 Awaitable on GitHub

CastNever

Replace never with a fallback type.

type CastNever<T, U> = [T] extends [never] ? U : T;

🔍 CastNever on GitHub

CreateContextOptions

Options for creating a request context from a Web Request.

export interface CreateContextOptions<TRuntime = unknown> {
    request: Request;
    host?: RequestHost<TRuntime> | undefined;
}

Properties

  • request The Web request being handled.

  • host Optional host metadata and hooks available to middleware.

🔍 CreateContextOptions on GitHub

Current

Outputs provided by the end of a middleware chain.

type Current<T extends AnyMiddlewareChain> = T['$MiddlewareChain']['current'];

🔍 Current on GitHub

EmptyMiddlewareChain

Empty chain type used when starting from no middleware.

export type EmptyMiddlewareChain<TRuntime = unknown> = MiddlewareChain<{
    initial: {
        env: {};
        properties: {};
    };
    current: {
        env: {};
        properties: {};
    };
    runtime: TRuntime;
}>;

🔍 EmptyMiddlewareChain on GitHub

Env

Environment variables provided by the end of a middleware chain.

type Env<T extends AnyMiddlewareChain> = Current<T>['env'];

🔍 Env on GitHub

EnvAccessor

The context.env method used to access environment variables.

export type EnvAccessor<TEnv extends object> = {
    <K extends keyof TEnv>(key: Extract<K, string>): TEnv[K];
    (key: never): string | undefined;
};

🔍 EnvAccessor on GitHub

Eval

Expand an object or intersection type into a readable property map.

type Eval<T> = {} & {
    [K in keyof T]: T[K] extends infer U ? U : never;
};

🔍 Eval on GitHub

ExtractMiddleware

Extract a Middleware type from a MiddlewareChain type.

export type ExtractMiddleware<T extends AnyMiddleware> = [T] extends [never] ? Middleware<{}, {}, any> : T extends AnyMiddlewareChain ? Middleware<Env<T>, Properties<T>, Runtime<T>> : T extends Middleware ? Extract<T, Middleware> : never;

🔍 ExtractMiddleware on GitHub

FetchHandler

A fetch-compatible request handler.

export type FetchHandler<TRequest extends Request = Request> = (request: TRequest) => Awaitable<Response>;

🔍 FetchHandler on GitHub

InputEnv

Environment variables required by the start of a middleware chain.

type InputEnv<T extends AnyMiddlewareChain> = Inputs<T>['env'];

🔍 InputEnv on GitHub

InputProperties

Context properties required by the start of a middleware chain.

type InputProperties<T extends AnyMiddlewareChain> = Inputs<T>['properties'];

🔍 InputProperties on GitHub

Inputs

Inputs required by the start of a middleware chain.

type Inputs<T extends AnyMiddlewareChain> = T['$MiddlewareChain']['initial'];

🔍 Inputs on GitHub

IsolatedContext

Context visible inside a chain wrapped with MiddlewareChain.isolate().

type IsolatedContext<T extends AnyMiddlewareChain> = RequestContext<InputEnv<T>, InputProperties<T>, Runtime<T>>;

🔍 IsolatedContext on GitHub

IsOptional

Detect whether a key is optional on an object type.

type IsOptional<T, K> = K extends keyof T ? T[K] extends Required<T>[K] ? false : true : true;

🔍 IsOptional on GitHub

Keys

Collect keys from each object in a union.

type Keys<T> = T extends any ? keyof T : never;

🔍 Keys on GitHub

Merge

Merge a union of object types (possibly undefined) into a single object type.

FIXME: Optional properties resolve as foo: Foo | undefined instead of foo?: Foo.

type Merge<TSource extends object, TOverrides extends object | undefined> = Eval<Omit<CastNever<TSource, {}>, Keys<TOverrides>> & {
    [K in Keys<TOverrides>]: TOverrides extends any ? MergeProperty<CastNever<TSource, {}>, TOverrides, K> : never;
}>;

🔍 Merge on GitHub

MergeProperty

Resolve one property after applying an override object to a source object.

type MergeProperty<TSource, TOverrides, K> = (K extends keyof TOverrides ? PossiblyUndefined<TOverrides, K> extends true ? TOverrides[K] : Exclude<TOverrides[K], undefined> : never) | (IsOptional<TOverrides, K> extends true ? K extends keyof TSource ? TSource[K] : undefined : never) extends infer TProperty ? TProperty : never;

🔍 MergeProperty on GitHub

Middleware

Middleware that can end the request or extend the downstream context.

export type Middleware<TEnv extends object = any, TProperties extends object = {}, TRuntime = any> = {
    (context: RequestContext<TEnv, TProperties, TRuntime>): Awaitable<Response | RequestPlugin | void>;
    $Middleware?: MiddlewareTypes & {
        initial: {
            env: TEnv;
            properties: TProperties;
        };
    };
};

Remarks

Return a Response to stop request-phase processing, return a RequestPlugin to add context data for later middleware, or return nothing to continue unchanged. Use context.onResponse or a plugin onResponse property to observe or replace the final response.

Properties

  • $Middleware This property won't exist at runtime. It contains type information for inference purposes.

🔍 Middleware on GitHub

MiddlewareContext

Extract a RequestContext type from a MiddlewareChain type.

When type T is never, a default context is returned.

export type MiddlewareContext<T extends AnyMiddlewareChain | AnyMiddleware[]> = [
    T
] extends [never] ? RequestContext<{}, never, unknown> : T extends AnyMiddlewareChain ? RequestContext<Env<T>, Properties<T>, Runtime<T>> : T extends AnyMiddleware[] ? MiddlewareContext<MiddlewareChain<ApplyMiddlewares<T>>> : never;

🔍 MiddlewareContext on GitHub

MiddlewareInputs

Inputs required by a middleware or chain.

type MiddlewareInputs<T extends AnyMiddleware> = T extends AnyMiddlewareChain ? Inputs<T> : T extends Middleware<infer TEnv, infer TProperties> ? {
    env: TEnv;
    properties: TProperties;
} : never;

🔍 MiddlewareInputs on GitHub

MiddlewareRuntime

Runtime type associated with a middleware or chain.

type MiddlewareRuntime<T extends AnyMiddleware> = T extends AnyMiddlewareChain ? Runtime<T> : T extends Middleware<any, any, infer TRuntime> ? TRuntime : never;

🔍 MiddlewareRuntime on GitHub

MiddlewareTypes

Type metadata carried by middleware chains and handlers.

export type MiddlewareTypes<TEnv extends object = object, TProperties extends object = object, TRuntime = unknown> = {
    initial: {
        env: TEnv;
        properties: TProperties;
    };
    current: {
        env: TEnv;
        properties: TProperties;
    };
    runtime: TRuntime;
};

Properties

  • initial Values expected by the start of the chain.

  • current Values provided by the end of the chain.

  • runtime Values from the host runtime.

🔍 MiddlewareTypes on GitHub

PossiblyUndefined

Detect whether a property type accepts undefined.

type PossiblyUndefined<T, K extends keyof T> = undefined extends Required<T>[K] ? true : false;

🔍 PossiblyUndefined on GitHub

Properties

Context properties provided by the end of a middleware chain.

type Properties<T extends AnyMiddlewareChain> = Current<T>['properties'];

🔍 Properties on GitHub

RequestContext

An extensible Web request context object.

NOTE: When using this type on the right side of an extends clause, you should prefer RequestContext<any> over RequestContext (no type parameters), as the default type is stricter.

export type RequestContext<TEnv extends object = any, TProperties extends object = {}, TRuntime = any> = WebRequestContext<TRuntime, TEnv> & CastNever<TProperties, unknown>;

🔍 RequestContext on GitHub

RequestHandler

Callable middleware chain that always resolves to a Response.

export interface RequestHandler<T extends MiddlewareTypes = any> extends MiddlewareChain<T> {
    (context: RequestContext<any, any, T['runtime']>): Awaitable<Response>;
}

🔍 RequestHandler on GitHub

RequestHost

Host-provided request metadata and lifecycle hooks.

export interface RequestHost<TRuntime = unknown> {
    env?(variable: string): unknown;
    ip?: string;
    runtime?: TRuntime;
    waitUntil?(promise: Promise<unknown>): void;
}

Properties

  • env Read an environment variable supplied by the host.

  • ip Client IP address supplied by the host, when available.

  • runtime Runtime-specific host metadata, such as srvx runtime details.

  • waitUntil Schedule work that should continue after a response is produced.

🔍 RequestHost on GitHub

RequestHostFactory

Build host metadata for each request passed to a fetch handler.

export type RequestHostFactory<TRuntime = unknown, TRequest extends Request = Request> = (request: TRequest) => RequestHost<TRuntime> | undefined;

🔍 RequestHostFactory on GitHub

RequestMiddleware

A middleware function that runs before a response is finalized.

export type RequestMiddleware<T extends AnyMiddlewareChain = MiddlewareChain> = (context: RequestContext<InputEnv<T>, InputProperties<T>, Runtime<T>>) => Awaitable<Response | RequestPlugin | void>;

🔍 RequestMiddleware on GitHub

RequestPlugin

The object returned by a request middleware and merged into the active request context for downstream middleware.

May contain special properties:

  • env: Add type-safe environment variables.
  • runtime: Narrow context.host.runtime at the type level.
  • onResponse: Register a response callback.
export type RequestPlugin = Record<string, unknown> & ReservedProperties;

Remarks

Plain properties are defined on the request context. If a later plugin uses the same property name, the later descriptor replaces the earlier one.

🔍 RequestPlugin on GitHub

ReservedProperties

Special request plugin keys consumed by the middleware runner.

type ReservedProperties = {
    env?: object;
    runtime?: object;
    onResponse?: ResponseCallback;
};

Properties

  • env Add type-safe environment variables. These are accessed with the env() method on the request context.

  • runtime Narrow context.host.runtime for downstream middleware.

  • onResponse Intercept the response before it's sent to the client.

🔍 ReservedProperties on GitHub

ResponseCallback

Callback that observes or replaces the generated response.

export type ResponseCallback = (response: Response) => Awaitable<Response | void>;

🔍 ResponseCallback on GitHub

Runtime

Host runtime data carried through a middleware chain.

type Runtime<T extends AnyMiddlewareChain> = T['$MiddlewareChain']['runtime'];

🔍 Runtime on GitHub

ToFetchHandlerOptions

Options used when adapting a request handler into a fetch handler.

export interface ToFetchHandlerOptions<TRuntime = unknown, TRequest extends Request = Request> {
    host?: RequestHost<TRuntime> | RequestHostFactory<TRuntime, TRequest> | undefined;
}

Properties

  • host Static host metadata or a per-request host metadata factory.

🔍 ToFetchHandlerOptions on GitHub

WebRequestContext

Base Web request context shared by all middleware.

export interface WebRequestContext<TRuntime, TEnv extends object> {
    request: Request;
    host: RequestHost<TRuntime>;
    env: EnvAccessor<TEnv>;
    passThrough(): never;
    waitUntil(promise: Promise<unknown>): void;
    url: URL;
    setHeader(name: string, value: string): void;
    onResponse(callback: ResponseCallback): void;
}

Properties

  • request The Web request currently being handled.

  • host Host metadata and lifecycle hooks for the current request.

  • env Type-safe access to environment values.

  • passThrough Skip the remaining middleware in the current chain.

  • waitUntil Schedule work through host.waitUntil when the host supports it.

  • url The request.url string parsed into a URL object. Parsing is performed on-demand and the result is cached.

  • setHeader Set a response header from a request middleware.

    Response middlewares should use response.headers.set() instead.

  • onResponse Add a callback to be called when a response is generated.

🔍 WebRequestContext on GitHub