UNPKG

h3

Version:

Minimal H(TTP) framework built for high performance and portability.

120 lines (119 loc) 5.7 kB
import { MatchResult, MatchedRouteRule, MatchedRouteRules, NormalizedRouteRules, RuleHandlers } from "./h3.mjs"; interface PreMergedRouteRules { /** The pattern this layer is registered at (params lookup key). */ route: string; /** * Containment depth of {@link route}: how many patterns of the rule set * strictly subsume it. Any set of simultaneously matched patterns is a * containment chain (partial overlaps are rejected below), and depth * strictly increases along a chain — if `a` subsumes `b` then every subsumer * of `a` also subsumes `b`, plus `a` itself — so the most specific matched * layer is the one with the highest rank. * * Layer *position* cannot be used for this — see {@link RouteRuleEntry.rank} * for rou3's documented optional-syntax carve-out and what taking the last * layer costs. The chain-cleanliness check below cannot catch that case * either: those pairs are `subset`, not `partial`, so nothing throws and the * compiler's fail-safe fallback never fires. */ rank: number; rules: PreMergedRouteRuleEntry[]; /** * Rule names this chain reset with `false`, when any. The reset itself is * applied here at build time, so the resolved `rules` cannot show it — but the * cross-reading union has to tell "reset by this path" apart from "never * matched" to stop a broader alternate reading resurrecting a permission * (`mergeMatchedRouteRules`). Plain mode reads the same information off the * `false` entries it merges per request; recording it keeps both modes — and * the compiled table — resolving identically. */ resets?: string[]; } interface PreMergedRouteRuleEntry extends RouteRuleEntry { /** * Patterns whose layers contributed to this rule (chain order), when different * from `[route]` — used to merge exact per-rule `params` from only the layers * that carried the rule. */ paramRoutes?: string[]; } /** Decide whether an alternate path reading may override a matched rule. */ type RouteOverridePredicate = (currentRoute: string, incomingRoute: string) => boolean; /** One normalized rule registered for a route pattern. */ export interface RouteRuleEntry { name: string; route: string; options: unknown; handler?: MatchedRouteRule["handler"]; /** * Pattern-containment depth. Required because rou3 result order is not * containment order for optional/modifier parameters. */ rank?: number; } /** A matched route layer containing rule data and route parameters. */ export interface RouteRuleLayer { data: RouteRuleEntry[] | PreMergedRouteRules; params?: Record<string, string>; } /** * Merge served-path and alternate-reading layers. Alternate readings may add * rules but override existing ones only when `canOverride` permits it. */ export declare function mergeMatchedRouteRules(rawLayers: RouteRuleLayer[] | undefined, altLayers?: readonly (RouteRuleLayer[] | undefined)[], canOverride?: RouteOverridePredicate): MatchedRouteRules; export interface RouteRulesMatcherOptions { /** * Base URL prefix for all rule patterns (trailing slash trimmed). */ baseURL?: string; /** * Add or override rule handler constructors by name. * Registry defaults are `headers`, `redirect`, `cors`; `cache` and * `proxy` are opt-in (register them from `h3/rules/cache` / `h3/rules/proxy`). * Setting a name to `undefined` makes that rule data-only. */ handlers?: RuleHandlers; /** * Pre-merge compatible pattern chains at startup. Throws for partial overlaps * or patterns that cannot be analyzed, such as regex parameters. */ preMerge?: boolean; } export interface MatcherMemoizeOptions { /** * Maximum number of memoized `method + pathname` entries. On overflow the * oldest entry not hit since the eviction hand last passed it is evicted * (SIEVE). `0` (or negative) disables memoization. * @default 1024 */ max?: number; } export type RouteRulesMatcher = (method: string, pathname: string) => MatchResult; /** A `findAllRoutes`-compatible lookup, as produced by `rou3/compiler` codegen. */ export type FindRouteRules = (method: string, pathname: string) => RouteRuleLayer[]; /** * Create a route-rules matcher from a **normalized** rule set (see {@link normalizeRouteRules}). * Returns `(method, pathname) => { routeRules, matchedRules, routeRuleMiddleware }`. */ export declare function createRouteRulesMatcher(rules: Record<string, NormalizedRouteRules>, opts?: RouteRulesMatcherOptions): RouteRulesMatcher; /** * Create a matcher from a `findAllRoutes`-compatible lookup, typically generated * by `h3/rules/compiler`. * * Results are not memoized. The default override guard fails closed when route * specificity is ambiguous. */ export declare function createMatcherFromFind(findRouteRules: FindRouteRules, canOverride?: RouteOverridePredicate): RouteRulesMatcher; /** * Memoize matches by method and pathname with a 1024-entry cap by default. * Returned objects are shared and must be treated as immutable. * * Eviction is SIEVE: insertion-ordered like a FIFO, but an entry hit since the * hand last passed it survives that pass. Plain FIFO evicts a hot static path * on the same schedule as the one-shot dynamic paths that displaced it, so a * mixed workload (a small hot set plus high-cardinality `/:id` traffic) loses * cached entries it is about to ask for again. Unlike LRU this costs no map * mutation on a hit — only a boolean store — which keeps the hot path the * single lookup the memo exists to provide. */ export declare function memoizeRouteRulesMatcher(matcher: RouteRulesMatcher, opts?: MatcherMemoizeOptions): RouteRulesMatcher;