implementing routing and streamline tsx runtime
This commit is contained in:
parent
3d733cfe0b
commit
4af7b21171
14 changed files with 820 additions and 451 deletions
68
src/middleware.ts
Normal file
68
src/middleware.ts
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* Copyright (c) 2025 favewa
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
import { HtmlStream } from "./http.ts";
|
||||
import { Promisable } from "./utils.ts";
|
||||
|
||||
export interface Context<Params = Record<string, string>> {
|
||||
readonly request: Request;
|
||||
readonly url: URL;
|
||||
readonly method: string;
|
||||
readonly params: Params;
|
||||
readonly pattern: URLPatternResult;
|
||||
readonly html: HtmlStream;
|
||||
readonly signal: AbortSignal;
|
||||
state: Map<string | symbol, unknown>;
|
||||
}
|
||||
|
||||
export async function createContext<P = Record<string, string>>(
|
||||
request: Request,
|
||||
pattern: URLPatternResult,
|
||||
html: HtmlStream,
|
||||
): Promise<Context<P>> {
|
||||
return {
|
||||
request,
|
||||
url: new URL(request.url),
|
||||
method: request.method,
|
||||
params: (pattern.pathname.groups || {}) as P,
|
||||
pattern,
|
||||
html,
|
||||
signal: request.signal,
|
||||
state: new Map(),
|
||||
};
|
||||
}
|
||||
|
||||
export interface Handler<P = Record<string, string>> {
|
||||
(ctx: Context<P>): Promisable<Response | void>;
|
||||
}
|
||||
|
||||
export interface Middleware {
|
||||
(ctx: Context, next: () => Promise<Response>): Promisable<Response>;
|
||||
}
|
||||
|
||||
export function compose(
|
||||
middlewares: readonly Middleware[],
|
||||
handler: Handler,
|
||||
): Handler {
|
||||
if (!middlewares.length) return handler;
|
||||
|
||||
return (ctx) => {
|
||||
let index = -1;
|
||||
|
||||
async function dispatch(i: number): Promise<Response> {
|
||||
if (i <= index) throw new Error("next() called multiple times");
|
||||
index = i;
|
||||
|
||||
const fn = i < middlewares.length ? middlewares[i] : handler;
|
||||
if (!fn) throw new Error("No handler found");
|
||||
|
||||
const result = await fn(ctx, () => dispatch(i + 1));
|
||||
if (!result) throw new Error("Handler must return Response");
|
||||
return result;
|
||||
}
|
||||
|
||||
return dispatch(0);
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue