routup 5.0.1 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bun.d.mts +2 -2
- package/dist/bun.mjs +2 -2
- package/dist/cloudflare.d.mts +2 -2
- package/dist/cloudflare.mjs +2 -2
- package/dist/deno.d.mts +2 -2
- package/dist/deno.mjs +2 -2
- package/dist/generic.d.mts +2 -2
- package/dist/generic.mjs +2 -2
- package/dist/{index-B5wJZ2-A.d.mts → index-BFl_WPX9.d.mts} +26 -5
- package/dist/node.d.mts +2 -2
- package/dist/node.mjs +2 -2
- package/dist/service-worker.d.mts +2 -2
- package/dist/service-worker.mjs +2 -2
- package/dist/{src-DwBb11Ty.mjs → src-BYuhKm-d.mjs} +47 -23
- package/dist/src-BYuhKm-d.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/src-DwBb11Ty.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"src-BYuhKm-d.mjs","names":[],"sources":["../src/constants.ts","../src/response/helpers/cache.ts","../src/error/module.ts","../src/response/helpers/event-stream/utils.ts","../src/response/helpers/event-stream/module.ts","../src/utils/header.ts","../src/utils/etag/module.ts","../src/utils/object.ts","../src/utils/etag/utils.ts","../src/utils/trust-proxy/module.ts","../src/utils/is-instance.ts","../src/utils/mime.ts","../src/utils/method.ts","../src/utils/path.ts","../src/utils/url.ts","../src/response/helpers/header.ts","../src/response/helpers/utils.ts","../src/response/helpers/header-disposition.ts","../src/response/helpers/header-content-type.ts","../src/error/is.ts","../src/error/create.ts","../src/response/to-response.ts","../src/response/helpers/send-accepted.ts","../src/response/helpers/send-created.ts","../src/response/helpers/send-file.ts","../src/request/helpers/header.ts","../src/request/helpers/negotiator.ts","../src/request/helpers/header-accept.ts","../src/response/helpers/send-format.ts","../src/response/helpers/send-redirect.ts","../src/response/helpers/send-stream.ts","../src/event/module.ts","../src/dispatcher/module.ts","../src/handler/constants.ts","../src/hook/constants.ts","../src/hook/module.ts","../src/path/matcher.ts","../src/path/utils.ts","../src/handler/utils.ts","../src/handler/module.ts","../src/handler/core/define.ts","../src/handler/error/define.ts","../src/handler/adapters/node/define.ts","../src/handler/adapters/web/is.ts","../src/handler/adapters/web/define.ts","../src/handler/is.ts","../src/request/helpers/cache.ts","../src/request/helpers/header-accept-charset.ts","../src/request/helpers/header-accept-encoding.ts","../src/request/helpers/header-accept-language.ts","../src/request/helpers/header-content-type.ts","../src/request/helpers/hostname.ts","../src/request/helpers/ip.ts","../src/request/helpers/protocol.ts","../src/plugin/error/constants.ts","../src/plugin/error/is.ts","../src/plugin/error/module.ts","../src/plugin/error/sub/already-installed.ts","../src/plugin/error/sub/install.ts","../src/plugin/error/sub/not-installed.ts","../src/plugin/is.ts","../src/router/options.ts","../src/router/constants.ts","../src/router/utils.ts","../src/router/module.ts"],"sourcesContent":["export const MethodName = {\n GET: 'GET',\n POST: 'POST',\n PUT: 'PUT',\n PATCH: 'PATCH',\n DELETE: 'DELETE',\n OPTIONS: 'OPTIONS',\n HEAD: 'HEAD',\n} as const;\n\nexport type MethodName = typeof MethodName[keyof typeof MethodName];\n\nexport const HeaderName = {\n ACCEPT: 'accept',\n ACCEPT_CHARSET: 'accept-charset',\n ACCEPT_ENCODING: 'accept-encoding',\n ACCEPT_LANGUAGE: 'accept-language',\n ACCEPT_RANGES: 'accept-ranges',\n ALLOW: 'allow',\n CACHE_CONTROL: 'cache-control',\n CONTENT_DISPOSITION: 'content-disposition',\n CONTENT_ENCODING: 'content-encoding',\n CONTENT_LENGTH: 'content-length',\n CONTENT_RANGE: 'content-range',\n CONTENT_TYPE: 'content-type',\n CONNECTION: 'connection',\n COOKIE: 'cookie',\n ETag: 'etag',\n HOST: 'host',\n IF_MODIFIED_SINCE: 'if-modified-since',\n IF_NONE_MATCH: 'if-none-match',\n LAST_MODIFIED: 'last-modified',\n LOCATION: 'location',\n RANGE: 'range',\n RATE_LIMIT_LIMIT: 'ratelimit-limit',\n RATE_LIMIT_REMAINING: 'ratelimit-remaining',\n RATE_LIMIT_RESET: 'ratelimit-reset',\n RETRY_AFTER: 'retry-after',\n SET_COOKIE: 'set-cookie',\n TRANSFER_ENCODING: 'transfer-encoding',\n X_ACCEL_BUFFERING: 'x-accel-buffering',\n X_FORWARDED_HOST: 'x-forwarded-host',\n X_FORWARDED_FOR: 'x-forwarded-for',\n X_FORWARDED_PROTO: 'x-forwarded-proto',\n} as const;\n\nexport type HeaderName = typeof HeaderName[keyof typeof HeaderName];\n","import type { IRoutupEvent } from '../../event/index.ts';\n\nexport type ResponseCacheHeadersOptions = {\n maxAge?: number,\n modifiedTime?: string | Date,\n cacheControls?: string[]\n};\n\nexport function setResponseCacheHeaders(event: IRoutupEvent, options?: ResponseCacheHeadersOptions) {\n options = options || {};\n\n const cacheControls = ['public'].concat(options.cacheControls || []);\n\n if (options.maxAge !== undefined) {\n cacheControls.push(`max-age=${+options.maxAge}`, `s-maxage=${+options.maxAge}`);\n }\n\n if (options.modifiedTime) {\n const modifiedTime = typeof options.modifiedTime === 'string' ?\n new Date(options.modifiedTime) :\n options.modifiedTime;\n\n event.response.headers.set('last-modified', modifiedTime.toUTCString());\n }\n\n event.response.headers.set('cache-control', cacheControls.join(', '));\n}\n","import { HTTPError } from '@ebec/http';\nimport type { HTTPErrorInput } from '@ebec/http';\n\nexport type { HTTPErrorInput };\n\nexport const ErrorSymbol = Symbol.for('RoutupError');\n\nexport class RoutupError extends HTTPError {\n readonly '@instanceof' = ErrorSymbol;\n\n constructor(input: HTTPErrorInput = {}) {\n super(input);\n this.name = 'RoutupError';\n }\n}\n","import type { EventStreamMessage } from './types.ts';\n\nfunction stripNewlines(value: string) : string {\n return value.replace(/[\\r\\n]/g, '');\n}\n\nexport function serializeEventStreamMessage(message: EventStreamMessage): string {\n let result = '';\n\n if (message.id) {\n result += `id: ${stripNewlines(message.id)}\\n`;\n }\n\n if (message.event) {\n result += `event: ${stripNewlines(message.event)}\\n`;\n }\n\n if (\n typeof message.retry === 'number' &&\n Number.isInteger(message.retry)\n ) {\n result += `retry: ${message.retry}\\n`;\n }\n\n const lines = message.data.replace(/\\r/g, '').split('\\n');\n for (const line of lines) {\n result += `data: ${line}\\n`;\n }\n result += '\\n';\n\n return result;\n}\n","import { HeaderName } from '../../../constants.ts';\nimport type { IRoutupEvent } from '../../../event/index.ts';\nimport { RoutupError } from '../../../error/module.ts';\nimport type { EventStreamMessage } from './types.ts';\nimport { serializeEventStreamMessage } from './utils.ts';\n\nexport type EventStreamOptions = {\n maxMessageSize?: number,\n};\n\nexport type EventStreamHandle = {\n write(message: string | EventStreamMessage): boolean;\n end(): void;\n response: Response;\n};\n\nexport function createEventStream(\n event: IRoutupEvent,\n options?: EventStreamOptions,\n): EventStreamHandle {\n if (options?.maxMessageSize !== undefined) {\n if (!Number.isInteger(options.maxMessageSize) || options.maxMessageSize < 0) {\n throw new RoutupError('maxMessageSize must be a non-negative integer.');\n }\n }\n\n let controller: ReadableStreamDefaultController<Uint8Array>;\n let closed = false;\n const encoder = new TextEncoder();\n\n const stream = new ReadableStream<Uint8Array>({\n start(ctrl) {\n controller = ctrl;\n },\n cancel() {\n closed = true;\n },\n });\n\n const headers = new Headers(event.response.headers);\n headers.set(HeaderName.CONTENT_TYPE, 'text/event-stream');\n headers.set(HeaderName.CACHE_CONTROL, 'private, no-cache, no-store, no-transform, must-revalidate, max-age=0');\n headers.set(HeaderName.X_ACCEL_BUFFERING, 'no');\n headers.set(HeaderName.CONNECTION, 'keep-alive');\n\n const response = new Response(stream, {\n status: event.response.status,\n headers,\n });\n\n const handle: EventStreamHandle = {\n write(message: string | EventStreamMessage): boolean {\n if (closed) return false;\n\n if (typeof message === 'string') {\n return handle.write({ data: message });\n }\n\n const serialized = serializeEventStreamMessage(message);\n\n if (options?.maxMessageSize !== undefined) {\n const serializedSize = encoder.encode(serialized).byteLength;\n if (serializedSize > options.maxMessageSize) {\n return false;\n }\n }\n\n controller.enqueue(encoder.encode(serialized));\n return true;\n },\n\n end(): void {\n if (closed) return;\n\n closed = true;\n controller.close();\n },\n\n response,\n };\n\n return handle;\n}\n","export function sanitizeHeaderValue(value: string) : string {\n return value.replace(/[\\r\\n]/g, '');\n}","import { subtle } from 'uncrypto';\nimport type { EtagOptions } from './types.ts';\n\nasync function sha1(str: string) : Promise<string> {\n const enc = new TextEncoder();\n const hash = await subtle.digest('SHA-1', enc.encode(str));\n\n return btoa(String.fromCharCode(...new Uint8Array(hash)));\n}\n\n/**\n * Generate an ETag.\n */\nexport async function generateETag(input: string) : Promise<string> {\n if (input.length === 0) {\n // fast-path empty\n return '\"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk\"';\n }\n\n const hash = await sha1(input);\n\n return `\"${input.length.toString(16)}-${hash.substring(0, 27)}\"`;\n}\n\n/**\n * Create a simple ETag.\n */\nexport async function createEtag(\n input: string,\n options: EtagOptions = {},\n) : Promise<string> {\n // generate entity tag\n const tag = await generateETag(input);\n\n return options.weak ?\n `W/${tag}` :\n tag;\n}\n","export function isObject(item: unknown) : item is Record<string, any> {\n return (\n !!item &&\n typeof item === 'object' &&\n !Array.isArray(item)\n );\n}\n\nexport function setProperty(\n record: Record<PropertyKey, any>,\n property: PropertyKey,\n value: any,\n): void {\n (record as any)[property] = value;\n}\n\nexport function getProperty<T = any>(\n req: Record<PropertyKey, any>,\n property: PropertyKey,\n): T {\n return (req as any)[property];\n}\n","import { merge } from 'smob';\nimport { isObject } from '../object.ts';\nimport { createEtag } from './module.ts';\nimport type { EtagFn, EtagOptions } from './types.ts';\n\nconst textEncoder = /* @__PURE__ */ new TextEncoder();\n\nexport function buildEtagFn(input?: boolean | EtagOptions | EtagFn) : EtagFn {\n if (typeof input === 'function') {\n return input;\n }\n\n input = input ?? true;\n\n if (input === false) {\n return () => Promise.resolve(undefined);\n }\n\n let options : EtagOptions = { weak: true };\n\n if (isObject(input)) {\n options = merge(input, options);\n }\n\n return async (body: string, size?: number) => {\n if (typeof options.threshold !== 'undefined') {\n const measured = size ?? textEncoder.encode(body).byteLength;\n\n if (measured <= options.threshold) {\n return undefined;\n }\n }\n\n return createEtag(body, options);\n };\n}\n","import { compile } from 'proxy-addr';\nimport type { TrustProxyFn } from './type.ts';\n\nexport function buildTrustProxyFn(\n input?: boolean | number | string | string[] | TrustProxyFn,\n) : TrustProxyFn {\n if (typeof input === 'function') {\n return input;\n }\n\n if (input === true) {\n return () => true;\n }\n\n if (typeof input === 'number') {\n return (_address, hop) => hop < (input as number);\n }\n\n if (typeof input === 'string') {\n input = input.split(',')\n .map((value) => value.trim());\n }\n\n return compile(input || []);\n}\n","import { isObject } from './object.ts';\n\nexport function isInstance(\n input: unknown,\n sym: symbol,\n) {\n if (!isObject(input)) {\n return false;\n }\n\n return (input as { '@instanceof': symbol })['@instanceof'] === sym;\n}\n","import { get, getType } from 'mime-explorer';\n\nexport function getMimeType(type: string) : string | undefined {\n if (type.includes('/')) {\n return type;\n }\n\n return getType(type);\n}\n\nexport function getCharsetForMimeType(type: string) : string | undefined {\n if ((/^text\\/|^application\\/(javascript|json)/).test(type)) {\n return 'utf-8';\n }\n\n const meta = get(type);\n if (\n meta &&\n meta.charset\n ) {\n return meta.charset.toLowerCase();\n }\n\n return undefined;\n}\n","import type { MethodName } from '../constants.ts';\n\nexport function toMethodName(input: string | undefined) : MethodName | undefined;\nexport function toMethodName(input: string | undefined, alt: MethodName) : MethodName;\nexport function toMethodName(\n input?: string,\n alt?: MethodName,\n) : MethodName | undefined {\n if (input) {\n return input.toUpperCase() as MethodName;\n }\n\n return alt;\n}\n","/**\n * Based on https://github.com/unjs/pathe v1.1.1 (055f50a6f1131f4e5c56cf259dd8816168fba329)\n */\n\nfunction normalizeWindowsPath(input = '') {\n if (!input || !input.includes('\\\\')) {\n return input;\n }\n\n return input.replace(/\\\\/g, '/');\n}\n\nconst EXTNAME_RE = /.(\\.[^./]+)$/;\nexport function extname(input: string) {\n const match = EXTNAME_RE.exec(normalizeWindowsPath(input));\n return (match && match[1]) || '';\n}\n\nexport function basename(input: string, extension? :string) {\n const lastSegment = normalizeWindowsPath(input)\n .split('/')\n .pop();\n\n if (!lastSegment) {\n return input;\n }\n\n return extension && lastSegment.endsWith(extension) ?\n lastSegment.slice(0, -extension.length) :\n lastSegment;\n}\n","const TRAILING_SLASH_RE = /\\/$|\\/\\?/;\n\nexport function hasTrailingSlash(input = '', queryParams = false): boolean {\n if (!queryParams) {\n return input.endsWith('/');\n }\n\n return TRAILING_SLASH_RE.test(input);\n}\n\nexport function withoutTrailingSlash(input = '', queryParams = false): string {\n if (!queryParams) {\n return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || '/';\n }\n\n if (!hasTrailingSlash(input, true)) {\n return input || '/';\n }\n\n const [s0, ...s] = input.split('?');\n\n return (s0!.slice(0, -1) || '/') + (s.length ? `?${s.join('?')}` : '');\n}\n\nexport function withTrailingSlash(input = '', queryParams = false): string {\n if (!queryParams) {\n return input.endsWith('/') ? input : (`${input}/`);\n }\n\n if (hasTrailingSlash(input, true)) {\n return input || '/';\n }\n\n const [s0, ...s] = input.split('?');\n return `${s0}/${s.length ? `?${s.join('?')}` : ''}`;\n}\n\nexport function hasLeadingSlash(input = ''): boolean {\n return input.startsWith('/');\n}\n\nexport function withoutLeadingSlash(input = ''): string {\n return (hasLeadingSlash(input) ? input.substring(1) : input) || '/';\n}\n\nexport function withLeadingSlash(input = ''): string {\n return hasLeadingSlash(input) ? input : `/${input}`;\n}\n\nexport function cleanDoubleSlashes(input = ''): string {\n if (input.includes('://')) {\n return input.split('://')\n .map((str) => cleanDoubleSlashes(str))\n .join('://');\n }\n\n return input.replace(/\\/+/g, '/');\n}\n","import { sanitizeHeaderValue } from '../../utils/index.ts';\nimport type { IRoutupEvent } from '../../event/index.ts';\n\nexport function appendResponseHeader(\n event: IRoutupEvent,\n name: string,\n value: string | string[],\n) {\n const { headers } = event.response;\n\n if (Array.isArray(value)) {\n for (const v of value) {\n headers.append(name, sanitizeHeaderValue(v));\n }\n } else {\n headers.append(name, sanitizeHeaderValue(value));\n }\n}\n\nexport function appendResponseHeaderDirective(\n event: IRoutupEvent,\n name: string,\n value: string | string[],\n) {\n const { headers } = event.response;\n const existing = headers.get(name);\n\n if (!existing) {\n if (Array.isArray(value)) {\n headers.set(name, sanitizeHeaderValue(value.join('; ')));\n } else {\n headers.set(name, sanitizeHeaderValue(value));\n }\n return;\n }\n\n const directives = existing.split('; ');\n\n if (Array.isArray(value)) {\n directives.push(...value);\n } else {\n directives.push(value);\n }\n\n const unique = [...new Set(directives)];\n\n headers.set(name, sanitizeHeaderValue(unique.join('; ')));\n}\n","import { HeaderName } from '../../constants.ts';\nimport { extname, getCharsetForMimeType, getMimeType } from '../../utils/index.ts';\nimport type { IRoutupEvent } from '../../event/index.ts';\n\nexport function setResponseContentTypeByFileName(event: IRoutupEvent, fileName: string) {\n const ext = extname(fileName);\n if (ext) {\n let type = getMimeType(ext.substring(1));\n if (type) {\n const charset = getCharsetForMimeType(type);\n if (charset) {\n type += `; charset=${charset}`;\n }\n event.response.headers.set(HeaderName.CONTENT_TYPE, type);\n }\n }\n}\n","import { HeaderName } from '../../constants.ts';\nimport type { IRoutupEvent } from '../../event/index.ts';\nimport { setResponseContentTypeByFileName } from './utils.ts';\n\n// eslint-disable-next-line no-control-regex\nconst ENCODE_URL_ATTR_CHAR_REGEXP = /[\\x00-\\x20\"'()*,/:;<=>?@[\\\\\\]{}\\x7f]/g;\nconst NON_ASCII_REGEXP = /[^\\x20-\\x7e]/g;\nconst QUOTE_REGEXP = /[\\\\\"]/g;\nconst HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/;\nconst ASCII_TEXT_REGEXP = /^[\\x20-\\x7e]+$/;\nconst TOKEN_REGEXP = /^[!#$%&'*+.0-9A-Z^_`a-z|~-]+$/;\n\nfunction pencode(char: string): string {\n return `%${char.charCodeAt(0).toString(16).toUpperCase()}`;\n}\n\nfunction quoteString(value: string): string {\n return `\"${value.replace(QUOTE_REGEXP, '\\\\$&')}\"`;\n}\n\nfunction getAscii(value: string): string {\n return value.replace(NON_ASCII_REGEXP, '?');\n}\n\nfunction encodeExtended(value: string): string {\n return encodeURIComponent(value).replace(ENCODE_URL_ATTR_CHAR_REGEXP, pencode);\n}\n\nfunction formatFilename(value: string): string {\n if (TOKEN_REGEXP.test(value)) {\n return `filename=${value}`;\n }\n return `filename=${quoteString(value)}`;\n}\n\nfunction setDisposition(\n event: IRoutupEvent,\n type: 'attachment' | 'inline',\n filename?: string,\n) {\n let disposition: string = type;\n\n if (typeof filename === 'string') {\n setResponseContentTypeByFileName(event, filename);\n\n const isAsciiSafe = ASCII_TEXT_REGEXP.test(filename) &&\n !HEX_ESCAPE_REGEXP.test(filename);\n\n if (isAsciiSafe) {\n disposition += `; ${formatFilename(filename)}`;\n } else {\n disposition += `; ${formatFilename(getAscii(filename))}`;\n disposition += `; filename*=UTF-8''${encodeExtended(filename)}`;\n }\n }\n\n event.response.headers.set(\n HeaderName.CONTENT_DISPOSITION,\n disposition,\n );\n}\n\nexport function setResponseHeaderAttachment(event: IRoutupEvent, filename?: string) {\n setDisposition(event, 'attachment', filename);\n}\n\nexport function setResponseHeaderInline(event: IRoutupEvent, filename?: string) {\n setDisposition(event, 'inline', filename);\n}\n","import { HeaderName } from '../../constants.ts';\nimport { getMimeType } from '../../utils/index.ts';\nimport type { IRoutupEvent } from '../../event/index.ts';\n\nexport function setResponseHeaderContentType(event: IRoutupEvent, input: string, ifNotExists?: boolean) {\n if (ifNotExists) {\n const header = event.response.headers.get(HeaderName.CONTENT_TYPE);\n if (header) {\n return;\n }\n }\n\n const contentType = getMimeType(input);\n if (contentType) {\n event.response.headers.set(HeaderName.CONTENT_TYPE, contentType);\n }\n}\n","import { isHTTPError } from '@ebec/http';\nimport { isInstance } from '../utils/index.ts';\nimport type { RoutupError } from './module.ts';\nimport { ErrorSymbol } from './module.ts';\n\nexport function isError(input: unknown) : input is RoutupError {\n if (!isHTTPError(input)) {\n return false;\n }\n\n return isInstance(input, ErrorSymbol);\n}\n","import { isHTTPError } from '@ebec/http';\nimport type { HTTPErrorInput } from '@ebec/http';\nimport { isObject } from '../utils/index.ts';\nimport { isError } from './is.ts';\nimport { RoutupError } from './module.ts';\n\nfunction isNativeError(input: unknown): input is Error {\n return isObject(input) &&\n typeof (input as Record<string, unknown>).message === 'string' &&\n typeof (input as Record<string, unknown>).name === 'string';\n}\n\n/**\n * Create an internal error object by\n * - an existing RoutupError (returned as-is)\n * - an HTTPError (wrapped into a RoutupError preserving status)\n * - an Error (wrapped preserving message and cause)\n * - an options object (status, message, etc.)\n * - a message string\n *\n * @param input\n */\nexport function createError(input: HTTPErrorInput | unknown) : RoutupError {\n if (isError(input)) {\n return input;\n }\n\n if (typeof input === 'string') {\n return new RoutupError(input);\n }\n\n if (isHTTPError(input)) {\n return new RoutupError({\n message: input.message,\n code: input.code,\n status: input.status,\n redirectURL: input.redirectURL,\n cause: input,\n });\n }\n\n if (isNativeError(input)) {\n return new RoutupError({\n message: input.message,\n cause: input,\n });\n }\n\n if (!isObject(input)) {\n return new RoutupError();\n }\n\n const options = { ...input as Record<string, unknown> };\n if (options.cause === undefined) {\n options.cause = input;\n }\n\n return new RoutupError(options as HTTPErrorInput);\n}\n\n","import { createError } from '../error/create.ts';\nimport type { IRoutupEvent } from '../event/index.ts';\n\nfunction stripWeakPrefix(etag: string): string {\n return etag.startsWith('W/') ? etag.slice(2) : etag;\n}\n\nasync function applyEtag(\n body: string,\n event: IRoutupEvent,\n headers: Headers,\n): Promise<Response | undefined> {\n const etagFn = event.routerOptions.etag;\n if (!etagFn) return undefined;\n\n const etag = await etagFn(body);\n if (!etag) return undefined;\n\n headers.set('etag', etag);\n\n const ifNoneMatch = event.headers.get('if-none-match');\n if (ifNoneMatch && (ifNoneMatch === '*' || ifNoneMatch.split(',').some((t) => stripWeakPrefix(t.trim()) === stripWeakPrefix(etag)))) {\n return new Response(null, {\n status: 304,\n headers,\n });\n }\n\n return undefined;\n}\n\nexport async function toResponse(\n value: unknown,\n event: IRoutupEvent,\n): Promise<Response | undefined> {\n if (value === undefined) {\n return undefined;\n }\n\n if (value === null) {\n return new Response(null, {\n status: event.response.status,\n headers: event.response.headers,\n });\n }\n\n if (value instanceof Response) {\n return value;\n }\n\n const {\n status,\n headers,\n } = event.response;\n\n if (typeof value === 'string') {\n if (!headers.has('content-type')) {\n headers.set('content-type', 'text/plain; charset=utf-8');\n }\n\n const cached = await applyEtag(value, event, headers);\n if (cached) return cached;\n\n return new Response(value, {\n status,\n headers,\n });\n }\n\n if (value instanceof ArrayBuffer || value instanceof Uint8Array) {\n if (!headers.has('content-type')) {\n headers.set('content-type', 'application/octet-stream');\n }\n return new Response(value as BodyInit, {\n status,\n headers,\n });\n }\n\n if (value instanceof ReadableStream) {\n return new Response(value, {\n status,\n headers,\n });\n }\n\n if (value instanceof Blob) {\n if (!headers.has('content-type')) {\n headers.set('content-type', value.type || 'application/octet-stream');\n }\n return new Response(value, {\n status,\n headers,\n });\n }\n\n // object/array/number/boolean — JSON serialize\n if (!headers.has('content-type')) {\n headers.set('content-type', 'application/json; charset=utf-8');\n }\n\n let json: string;\n try {\n json = JSON.stringify(value);\n } catch (e) {\n throw createError({\n message: 'JSON serialization failed',\n status: 500,\n cause: e,\n });\n }\n\n const cached = await applyEtag(json, event, headers);\n if (cached) return cached;\n\n return new Response(json, {\n status,\n headers,\n });\n}\n","import type { IRoutupEvent } from '../../event/index.ts';\nimport { toResponse } from '../to-response.ts';\n\nexport async function sendAccepted(event: IRoutupEvent, data?: unknown): Promise<Response> {\n event.response.status = 202;\n\n return await toResponse(data ?? '', event) as Response;\n}\n","import type { IRoutupEvent } from '../../event/index.ts';\nimport { toResponse } from '../to-response.ts';\n\nexport async function sendCreated(event: IRoutupEvent, data?: unknown): Promise<Response> {\n event.response.status = 201;\n\n return await toResponse(data ?? '', event) as Response;\n}\n","import { HeaderName } from '../../constants.ts';\nimport { basename } from '../../utils/index.ts';\nimport type { IRoutupEvent } from '../../event/index.ts';\nimport { setResponseHeaderAttachment, setResponseHeaderInline } from './header-disposition.ts';\nimport { setResponseContentTypeByFileName } from './utils.ts';\n\nexport type SendFileContentOptions = {\n end?: number,\n start?: number;\n};\n\n/**\n * File metadata used by {@link sendFile}. All fields are optional, but each\n * missing field disables related response features:\n *\n * - `size` — without it, range requests, `Accept-Ranges`, `Content-Length`,\n * `ETag`, and `Last-Modified` are all omitted (the response is sent\n * without HTTP-level caching or seekability).\n * - `mtime` — without it, `Last-Modified` is omitted and the `ETag` is not\n * emitted (`ETag` requires both `size` and `mtime`).\n * - `name` — falls back to `SendFileOptions.name` when set; if both are\n * missing, no `Content-Disposition` or extension-derived\n * `Content-Type` is set.\n */\nexport type SendFileStats = {\n size?: number,\n mtime?: Date | number | string,\n name?: string\n};\n\nexport type SendFileDisposition = 'attachment' | 'inline';\n\nexport type SendFileContent = ReadableStream | ArrayBuffer | Uint8Array;\nexport type SendFileOptions = {\n stats: (() => Promise<SendFileStats> | SendFileStats) | SendFileStats,\n content: (options: SendFileContentOptions) => Promise<SendFileContent> | SendFileContent,\n /**\n * @deprecated Use `disposition: 'attachment'` instead. Kept for backwards\n * compatibility — when `disposition` is set, it takes precedence.\n */\n attachment?: boolean,\n disposition?: SendFileDisposition,\n name?: string\n};\n\nexport async function sendFile(\n event: IRoutupEvent,\n options: SendFileOptions,\n) : Promise<Response> {\n let stats : SendFileStats;\n if (typeof options.stats === 'function') {\n stats = await options.stats();\n } else {\n stats = options.stats;\n }\n\n const name = options.name || stats.name;\n const { headers } = event.response;\n\n const disposition = options.disposition ?? (options.attachment ? 'attachment' : undefined);\n\n if (name) {\n const fileName = basename(name);\n\n if (disposition) {\n const dispositionHeader = headers.get(HeaderName.CONTENT_DISPOSITION);\n if (!dispositionHeader) {\n if (disposition === 'inline') {\n setResponseHeaderInline(event, fileName);\n } else {\n setResponseHeaderAttachment(event, fileName);\n }\n }\n } else {\n setResponseContentTypeByFileName(event, fileName);\n }\n }\n\n const contentOptions : SendFileContentOptions = {};\n let statusCode = event.response.status;\n\n if (stats.size) {\n const rangeHeader = event.headers.get(HeaderName.RANGE);\n if (rangeHeader) {\n const [x, y] = rangeHeader.replace('bytes=', '')\n .split('-') as [string, string];\n\n const parsedStart = Number.parseInt(x, 10);\n const parsedEnd = Number.parseInt(y, 10);\n\n contentOptions.start = Number.isFinite(parsedStart) && parsedStart >= 0 ? parsedStart : 0;\n contentOptions.end = Number.isFinite(parsedEnd) && parsedEnd >= 0 ?\n Math.min(parsedEnd, stats.size - 1) :\n stats.size - 1;\n\n if (\n contentOptions.start >= stats.size ||\n contentOptions.start > contentOptions.end\n ) {\n const rangeHeaders = new Headers(headers);\n rangeHeaders.set(HeaderName.CONTENT_RANGE, `bytes */${stats.size}`);\n return new Response(null, {\n status: 416,\n headers: rangeHeaders,\n });\n }\n\n headers.set(HeaderName.CONTENT_RANGE, `bytes ${contentOptions.start}-${contentOptions.end}/${stats.size}`);\n headers.set(HeaderName.CONTENT_LENGTH, `${contentOptions.end - contentOptions.start + 1}`);\n statusCode = 206;\n } else {\n headers.set(HeaderName.CONTENT_LENGTH, `${stats.size}`);\n }\n\n headers.set(HeaderName.ACCEPT_RANGES, 'bytes');\n\n if (stats.mtime) {\n const mtime = new Date(stats.mtime);\n headers.set(HeaderName.LAST_MODIFIED, mtime.toUTCString());\n headers.set(HeaderName.ETag, `W/\"${stats.size}-${mtime.getTime()}\"`);\n }\n }\n\n const content = await options.content(contentOptions);\n\n return new Response(content as BodyInit, {\n status: statusCode,\n headers,\n });\n}\n","import type { IRoutupEvent } from '../../event/index.ts';\n\nexport function getRequestHeader(\n event: IRoutupEvent,\n name: string,\n) : string | null {\n return event.headers.get(name);\n}\n","import Negotiator from 'negotiator';\n\nimport type { IRoutupEvent } from '../../event/index.ts';\n\nconst NEGOTIATOR_KEY = Symbol.for('routup:negotiator');\n\nfunction headersToPlainObject(headers: Headers) : Record<string, string> {\n const result: Record<string, string> = {};\n headers.forEach((value, key) => {\n result[key] = value;\n });\n return result;\n}\n\nexport function useRequestNegotiator(event: IRoutupEvent) : Negotiator {\n let value = event.store[NEGOTIATOR_KEY] as Negotiator | undefined;\n if (value) {\n return value;\n }\n\n value = new Negotiator({ headers: headersToPlainObject(event.headers) });\n event.store[NEGOTIATOR_KEY] = value;\n return value;\n}\n","import { HeaderName } from '../../constants.ts';\nimport { getMimeType } from '../../utils/index.ts';\nimport type { IRoutupEvent } from '../../event/index.ts';\nimport { getRequestHeader } from './header.ts';\nimport { useRequestNegotiator } from './negotiator.ts';\n\nexport function getRequestAcceptableContentTypes(event: IRoutupEvent) : string[] {\n const negotiator = useRequestNegotiator(event);\n\n return negotiator.mediaTypes();\n}\n\nexport function getRequestAcceptableContentType(event: IRoutupEvent, input?: string | string[]) : string | undefined {\n input = input || [];\n\n const items = Array.isArray(input) ? input : [input];\n\n if (items.length === 0) {\n return getRequestAcceptableContentTypes(event).shift();\n }\n\n const header = getRequestHeader(event, HeaderName.ACCEPT);\n if (!header) {\n return items[0];\n }\n\n let polluted = false;\n const mimeTypes : string[] = [];\n for (const item of items) {\n const mimeType = getMimeType(item);\n if (mimeType) {\n mimeTypes.push(mimeType);\n } else {\n polluted = true;\n }\n }\n\n const negotiator = useRequestNegotiator(event);\n const matches = negotiator.mediaTypes(mimeTypes);\n if (matches.length > 0) {\n if (polluted) {\n return items[0];\n }\n\n return items[mimeTypes.indexOf(matches[0]!)];\n }\n\n return undefined;\n}\n","import { getRequestAcceptableContentType } from '../../request/helpers/header-accept.ts';\nimport type { IRoutupEvent } from '../../event/index.ts';\n\ntype ResponseFormatHandler = () => Response | unknown;\n\ntype ResponseFormats = {\n default: ResponseFormatHandler,\n [key: string]: ResponseFormatHandler,\n};\n\nexport function sendFormat(event: IRoutupEvent, input: ResponseFormats): Response | unknown | undefined {\n const {\n default: formatDefault,\n ...formats\n } = input;\n\n const contentTypes = Object.keys(formats);\n\n if (contentTypes.length === 0) {\n return formatDefault();\n }\n\n const contentType = getRequestAcceptableContentType(event, contentTypes);\n if (contentType && formats[contentType]) {\n return formats[contentType]();\n }\n\n return formatDefault();\n}\n","import { RoutupError } from '../../error/module.ts';\nimport { sanitizeHeaderValue } from '../../utils/index.ts';\nimport type { IRoutupEvent } from '../../event/index.ts';\n\nfunction escapeHtml(str: string) : string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n\nfunction isAllowedRedirectUrl(location: string) : boolean {\n // Block protocol-relative URLs (e.g. //evil.com)\n if (location.startsWith('//')) {\n return false;\n }\n\n if (location.startsWith('/') || location.startsWith('.')) {\n return true;\n }\n\n try {\n const url = new URL(location);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return true;\n }\n}\n\nexport function sendRedirect(event: IRoutupEvent, location: string, statusCode = 302): Response {\n if (!isAllowedRedirectUrl(location)) {\n throw new RoutupError({\n status: 400,\n message: 'Invalid redirect URL scheme.',\n });\n }\n\n const sanitizedLocation = sanitizeHeaderValue(location);\n const escapedLoc = escapeHtml(location);\n const html = `<!DOCTYPE html><html><head><meta http-equiv=\"refresh\" content=\"0; url=${escapedLoc}\"></head></html>`;\n\n const headers = new Headers(event.response.headers);\n headers.set('location', sanitizedLocation);\n headers.set('content-type', 'text/html; charset=utf-8');\n headers.delete('content-length');\n\n const response = new Response(html, {\n status: statusCode,\n headers,\n });\n\n return response;\n}\n","import type { IRoutupEvent } from '../../event/index.ts';\n\nexport function sendStream(event: IRoutupEvent, stream: ReadableStream): Response {\n const {\n status,\n headers,\n } = event.response;\n\n return new Response(stream, {\n status,\n headers,\n });\n}\n","import type { RouterOptions } from '../router/types.ts';\nimport type {\n IRoutupEvent,\n RoutupRequest,\n RoutupResponse,\n} from './types.ts';\n\nexport type RoutupEventCreateContext = {\n request: RoutupRequest;\n params: Record<string, any>;\n path: string;\n method: string;\n mountPath: string;\n headers: Headers;\n searchParams: URLSearchParams;\n response: RoutupResponse;\n store: Record<string | symbol, unknown>;\n signal: AbortSignal;\n routerOptions: () => RouterOptions;\n next: (event: IRoutupEvent, error?: Error) => Promise<Response | undefined>;\n};\n\nexport class RoutupEvent implements IRoutupEvent {\n readonly request: RoutupRequest;\n\n readonly params: Record<string, any>;\n\n readonly path: string;\n\n readonly method: string;\n\n readonly mountPath: string;\n\n readonly headers: Headers;\n\n readonly searchParams: URLSearchParams;\n\n readonly response: RoutupResponse;\n\n readonly store: Record<string | symbol, unknown>;\n\n readonly signal: AbortSignal;\n\n protected _context: RoutupEventCreateContext;\n\n protected _routerOptions?: RouterOptions;\n\n protected _nextCalled = false;\n\n protected _nextResult: Promise<Response | undefined> | undefined;\n\n protected _nextCalledDeferred: {\n promise: Promise<void>,\n resolve: () => void,\n } | undefined;\n\n constructor(context: RoutupEventCreateContext) {\n this._context = context;\n this.request = context.request;\n this.params = context.params;\n this.path = context.path;\n this.method = context.method;\n this.mountPath = context.mountPath;\n this.headers = context.headers;\n this.searchParams = context.searchParams;\n this.response = context.response;\n this.store = context.store;\n this.signal = context.signal;\n }\n\n get routerOptions(): RouterOptions {\n if (!this._routerOptions) {\n this._routerOptions = this._context.routerOptions();\n }\n\n return this._routerOptions;\n }\n\n get nextCalled(): boolean {\n return this._nextCalled;\n }\n\n get nextResult(): Promise<Response | undefined> | undefined {\n return this._nextResult;\n }\n\n whenNextCalled(): Promise<void> {\n if (!this._nextCalledDeferred) {\n let resolve!: () => void;\n const promise = new Promise<void>((r) => { resolve = r; });\n this._nextCalledDeferred = { promise, resolve };\n\n if (this._nextCalled) {\n resolve();\n }\n }\n\n return this._nextCalledDeferred.promise;\n }\n\n async next(error?: Error): Promise<Response | undefined> {\n if (this._nextCalled) {\n return this._nextResult;\n }\n\n this._nextCalled = true;\n this._nextResult = this._context.next(this, error);\n\n if (this._nextCalledDeferred) {\n this._nextCalledDeferred.resolve();\n }\n\n return this._nextResult;\n }\n}\n","import { FastURL } from 'srvx';\nimport type { RoutupError } from '../error/module.ts';\nimport type { RouterOptions, RouterPathNode } from '../router/types.ts';\nimport { toResponse } from '../response/index.ts';\nimport { buildEtagFn } from '../utils/index.ts';\nimport { RoutupEvent } from '../event/module.ts';\nimport type {\n IRoutupEvent,\n NextFn,\n RoutupRequest,\n RoutupResponse,\n} from '../event/types.ts';\nimport type { IDispatcherEvent } from './types.ts';\n\nexport class DispatcherEvent implements IDispatcherEvent {\n readonly request: RoutupRequest;\n\n params: Record<string, any>;\n\n path: string;\n\n readonly method: string;\n\n /**\n * Collected allowed methods (for OPTIONS).\n */\n methodsAllowed: Set<string>;\n\n mountPath: string;\n\n error?: RoutupError;\n\n routerPath: RouterPathNode[];\n\n protected _dispatched: boolean;\n\n protected _response?: RoutupResponse;\n\n protected _store?: Record<string | symbol, unknown>;\n\n /**\n * Cached parsed URL (avoids double-parsing).\n */\n protected _url: InstanceType<typeof FastURL>;\n\n /**\n * Continuation function for middleware onion model.\n */\n protected _next?: (event: IRoutupEvent, error?: Error) => Promise<Response | undefined>;\n\n protected _signal?: AbortSignal;\n\n protected _signalCleanup?: () => void;\n\n /**\n * Whether _next has already been called (guard against double-invocation).\n */\n protected _nextCalled: boolean;\n\n /**\n * The cached result of the next handler.\n */\n protected _nextResult?: Promise<Response | undefined>;\n\n // ------------------------------------------------------------------------\n\n constructor(request: RoutupRequest) {\n this.request = request;\n this._url = new FastURL(request.url);\n this.method = request.method;\n this.path = this._url.pathname;\n this.mountPath = '/';\n this.params = {};\n this.routerPath = [];\n this.methodsAllowed = new Set();\n this._dispatched = false;\n this._nextCalled = false;\n }\n\n // ------------------------------------------------------------------------\n\n get response(): RoutupResponse {\n if (!this._response) {\n this._response = { status: 200, headers: new Headers() };\n }\n\n return this._response;\n }\n\n get signal(): AbortSignal {\n if (!this._signal) {\n this._signal = this.request.signal;\n }\n\n return this._signal;\n }\n\n set signal(value: AbortSignal) {\n // Clean up listeners from a previous merge\n if (this._signalCleanup) {\n this._signalCleanup();\n this._signalCleanup = undefined;\n }\n\n if (value === this.request.signal) {\n this._signal = value;\n return;\n }\n\n const controller = new AbortController();\n const abort = (e?: Event) => {\n const reason = e?.target instanceof AbortSignal ?\n e.target.reason :\n undefined;\n this.request.signal.removeEventListener('abort', abort);\n value.removeEventListener('abort', abort);\n controller.abort(reason);\n };\n\n if (this.request.signal.aborted || value.aborted) {\n const reason = this.request.signal.aborted ?\n this.request.signal.reason :\n value.reason;\n controller.abort(reason);\n } else {\n this.request.signal.addEventListener('abort', abort, { once: true });\n value.addEventListener('abort', abort, { once: true });\n this._signalCleanup = () => {\n this.request.signal.removeEventListener('abort', abort);\n value.removeEventListener('abort', abort);\n };\n }\n\n this._signal = controller.signal;\n }\n\n get dispatched(): boolean {\n return this._dispatched;\n }\n\n set dispatched(value: boolean) {\n this._dispatched = value;\n }\n\n // ------------------------------------------------------------------------\n\n protected async next(event: IRoutupEvent, error?: Error): Promise<Response | undefined> {\n if (this._nextCalled) {\n return this._nextResult;\n }\n this._nextCalled = true;\n\n if (this._next) {\n this._nextResult = this._next(event, error);\n }\n\n return this._nextResult;\n }\n\n setNext(fn?: NextFn): void {\n if (fn) {\n this._next = async (event, error?: Error) => {\n const result = await fn(error);\n return toResponse(result, event);\n };\n } else {\n this._next = undefined;\n }\n\n this._nextCalled = false;\n this._nextResult = undefined;\n }\n\n // ------------------------------------------------------------------------\n\n build(signal?: AbortSignal): RoutupEvent {\n return new RoutupEvent({\n request: this.request,\n params: this.params,\n path: this.path,\n method: this.method,\n mountPath: this.mountPath,\n headers: this.request.headers,\n searchParams: new URLSearchParams(this._url.search),\n response: this.response,\n store: this.store,\n signal: signal ?? this.signal,\n routerOptions: () => this.resolveOptions(),\n next: (event: IRoutupEvent, error?: Error) => this.next(event, error),\n });\n }\n\n // ------------------------------------------------------------------------\n\n protected get store(): Record<string | symbol, unknown> {\n if (!this._store) {\n this._store = Object.create(null) as Record<string | symbol, unknown>;\n }\n\n return this._store!;\n }\n\n protected resolveOptions(): RouterOptions {\n const resolved: RouterOptions = {\n trustProxy: () => false,\n subdomainOffset: 2,\n etag: buildEtagFn(),\n proxyIpMax: 0,\n };\n\n for (let i = 0; i < this.routerPath.length; i++) {\n const node = this.routerPath[i]!;\n const entries = Object.entries(node.options);\n for (const entry of entries) {\n const [key, value] = entry!;\n if (typeof value !== 'undefined') {\n (resolved as Record<string, unknown>)[key] = value;\n }\n }\n }\n\n return resolved;\n }\n}\n","export const HandlerType = {\n CORE: 'core',\n ERROR: 'error',\n} as const;\n\nexport type HandlerType = typeof HandlerType[keyof typeof HandlerType];\n\nexport const HandlerSymbol = Symbol.for('Handler');\n","export const HookName = {\n REQUEST: 'request',\n RESPONSE: 'response',\n ERROR: 'error',\n\n CHILD_MATCH: 'childMatch',\n CHILD_DISPATCH_BEFORE: 'childDispatchBefore',\n CHILD_DISPATCH_AFTER: 'childDispatchAfter',\n} as const;\n\nexport type HookName = typeof HookName[keyof typeof HookName];\n","import type { IDispatcherEvent } from '../dispatcher/types.ts';\nimport { createError } from '../error/create.ts';\nimport { HookName } from './constants.ts';\nimport type {\n HookDefaultListener,\n HookErrorListener,\n HookListener,\n HookUnsubscribeFn,\n} from './types.ts';\n\ntype HookEntry = {\n fn: HookListener;\n priority: number;\n};\n\nexport class HookManager {\n protected items: Record<string, HookEntry[]>;\n\n // --------------------------------------------------\n\n constructor() {\n this.items = {};\n }\n\n // --------------------------------------------------\n\n addListener(\n name: HookName,\n fn: HookListener,\n priority: number = 0,\n ): HookUnsubscribeFn {\n this.items[name] = this.items[name] || [];\n\n const entry: HookEntry = { fn, priority };\n\n // Insert in sorted position (higher priority first)\n let i = 0;\n while (i < this.items[name].length && this.items[name][i]!.priority >= priority) {\n i++;\n }\n this.items[name].splice(i, 0, entry);\n\n return () => {\n this.removeListener(name, fn);\n };\n }\n\n removeListener(name: HookName): void;\n\n removeListener(name: HookName, fn: HookListener): void;\n\n removeListener(name: HookName, fn?: HookListener): void {\n if (!this.items[name]) {\n return;\n }\n\n if (typeof fn === 'undefined') {\n delete this.items[name];\n return;\n }\n\n if (typeof fn === 'function') {\n const index = this.items[name].findIndex((entry) => entry.fn === fn);\n if (index !== -1) {\n this.items[name].splice(index, 1);\n }\n }\n\n if (this.items[name].length === 0) {\n delete this.items[name];\n }\n }\n\n // --------------------------------------------------\n\n async trigger(\n name: HookName,\n event: IDispatcherEvent,\n ): Promise<void> {\n if (!this.items[name] || this.items[name].length === 0) {\n return;\n }\n\n try {\n for (let i = 0; i < this.items[name].length; i++) {\n const { fn } = this.items[name][i]!;\n await this.triggerListener(name, event, fn);\n\n if (event.dispatched) {\n if (event.error) {\n event.error = undefined;\n }\n return;\n }\n }\n } catch (e) {\n if (!event.error) {\n event.error = createError(e);\n }\n\n if (!this.isErrorListenerHook(name)) {\n await this.trigger(HookName.ERROR, event);\n\n if (event.dispatched) {\n if (event.error) {\n event.error = undefined;\n }\n }\n }\n }\n }\n\n private triggerListener(name: HookName, event: IDispatcherEvent, listener: HookListener) {\n if (this.isErrorListenerHook(name)) {\n if (event.error) {\n return (listener as HookErrorListener)(event);\n }\n return undefined;\n }\n\n return (listener as HookDefaultListener)(event);\n }\n\n private isErrorListenerHook(input: HookName) {\n return input === HookName.ERROR;\n }\n}\n","import type { Key } from 'path-to-regexp';\nimport { pathToRegexp } from 'path-to-regexp';\nimport type { Path, PathMatcherExecResult, PathMatcherOptions } from './type.ts';\n\nfunction decodeParam(val: unknown) {\n /* istanbul ignore next */\n if (typeof val !== 'string' || val.length === 0) {\n return val;\n }\n\n try {\n return decodeURIComponent(val);\n } catch {\n return val;\n }\n}\n\nexport class PathMatcher {\n protected path: Path;\n\n protected regexp : RegExp;\n\n protected regexpKeys : Key[] = [];\n\n protected regexpOptions: PathMatcherOptions;\n\n constructor(path: Path, options?: PathMatcherOptions) {\n this.path = path;\n\n this.regexpOptions = options || {};\n const regexp = pathToRegexp(path, options);\n\n this.regexp = regexp.regexp;\n this.regexpKeys = regexp.keys;\n }\n\n test(path: string) {\n return this.regexp.test(path);\n }\n\n exec(path: string) : PathMatcherExecResult | undefined {\n if (\n this.path === '/' &&\n this.regexpOptions.end === false\n ) {\n return {\n path: '/',\n params: Object.create(null),\n };\n }\n\n const match = this.regexp.exec(path);\n\n if (!match) {\n return undefined;\n }\n\n const params : Record<string, unknown> = Object.create(null);\n\n for (let i = 1; i < match.length; i++) {\n const key = this.regexpKeys[i - 1];\n if (!key) continue;\n const prop = key.name;\n const val = decodeParam(match[i]);\n\n if (typeof val !== 'undefined') {\n params[prop] = val;\n }\n }\n\n return {\n path: match[0],\n params,\n };\n }\n}\n","import type { Path } from './type.ts';\n\nexport function isPath(input: unknown): input is Path {\n return typeof input === 'string';\n}\n","import { MethodName } from '../constants.ts';\nimport { PathMatcher } from '../path/index.ts';\nimport type { Path } from '../path/index.ts';\nimport { withLeadingSlash } from '../utils/index.ts';\n\n/**\n * Build a `PathMatcher` for a handler-side path.\n *\n * Returns `undefined` when no path is supplied. The `end` flag controls\n * whether the matcher requires a full match (`true` for method handlers\n * matching exact routes) or accepts a prefix (`false` for middleware).\n */\nexport function buildHandlerPathMatcher(\n path: Path | undefined,\n end: boolean,\n): PathMatcher | undefined {\n if (typeof path === 'undefined') {\n return undefined;\n }\n\n const normalized = typeof path === 'string' ? withLeadingSlash(path) : path;\n return new PathMatcher(normalized, { end });\n}\n\n/**\n * Match a request method against a handler's bound method.\n *\n * - When the handler has no method bound, matches every request method.\n * - Otherwise matches when the request method is the same.\n * - HEAD requests additionally match GET handlers.\n */\nexport function matchHandlerMethod(\n handlerMethod: MethodName | undefined,\n requestMethod: MethodName,\n): boolean {\n return !handlerMethod ||\n requestMethod === handlerMethod ||\n (requestMethod === MethodName.HEAD && handlerMethod === MethodName.GET);\n}\n","import type { MethodName } from '../constants.ts';\nimport type { IDispatcher, IDispatcherEvent } from '../dispatcher/index.ts';\nimport { createError, isError } from '../error/index.ts';\nimport type { IRoutupEvent } from '../event/index.ts';\nimport { HookManager, HookName } from '../hook/index.ts';\nimport type { PathMatcher } from '../path/index.ts';\nimport { toResponse } from '../response/index.ts';\nimport type { RouterOptions } from '../router/types.ts';\nimport { toMethodName, withLeadingSlash } from '../utils/index.ts';\nimport { HandlerSymbol, HandlerType } from './constants.ts';\nimport type { HandlerOptions } from './types.ts';\nimport { buildHandlerPathMatcher } from './utils.ts';\n\nexport class Handler implements IDispatcher {\n readonly '@instanceof' = HandlerSymbol;\n\n protected config: HandlerOptions;\n\n protected hookManager: HookManager;\n\n protected pathMatcher: PathMatcher | undefined;\n\n readonly method: MethodName | undefined;\n\n // --------------------------------------------------\n\n constructor(handler: HandlerOptions) {\n this.config = handler;\n this.hookManager = new HookManager();\n\n this.mountHooks();\n\n if (typeof handler.path === 'string') {\n this.config.path = withLeadingSlash(handler.path);\n }\n\n this.pathMatcher = buildHandlerPathMatcher(this.config.path, !!this.config.method);\n this.method = this.config.method ? toMethodName(this.config.method) : undefined;\n }\n\n // --------------------------------------------------\n\n get type() {\n return this.config.type;\n }\n\n get path() {\n return this.config.path;\n }\n\n // --------------------------------------------------\n\n async dispatch(event: IDispatcherEvent): Promise<Response | undefined> {\n if (this.pathMatcher) {\n const pathMatch = this.pathMatcher.exec(event.path);\n if (pathMatch) {\n event.params = {\n ...event.params,\n ...pathMatch.params,\n };\n }\n }\n\n await this.hookManager.trigger(HookName.CHILD_DISPATCH_BEFORE, event);\n if (event.dispatched) {\n return undefined;\n }\n\n let response: Response | undefined;\n\n try {\n let result: unknown;\n\n // Build a preliminary event to access routerOptions for timeout resolution\n const previewEvent = event.build();\n const effectiveTimeout = this.resolveTimeout(previewEvent.routerOptions);\n\n // When a per-handler timeout is active, create a child AbortController\n // linked to the parent signal so the handler's signal aborts on timeout\n let childController: AbortController | undefined;\n let cleanupParentListener: (() => void) | undefined;\n let handlerEvent = previewEvent;\n\n if (effectiveTimeout) {\n const parentSignal = event.signal;\n childController = new AbortController();\n\n if (parentSignal.aborted) {\n childController.abort(parentSignal.reason);\n } else {\n const onAbort = () => childController!.abort(parentSignal.reason);\n parentSignal.addEventListener('abort', onAbort, { once: true });\n cleanupParentListener = () => parentSignal.removeEventListener('abort', onAbort);\n }\n\n // Rebuild with the child signal so the handler sees it via event.signal\n handlerEvent = event.build(childController.signal);\n }\n\n try {\n if (this.config.type === HandlerType.ERROR) {\n if (event.error) {\n const { fn } = this.config;\n const { error } = event;\n result = await this.executeWithTimeout(\n () => this.resolveHandlerResult(\n fn(error, handlerEvent),\n handlerEvent,\n ),\n handlerEvent.routerOptions,\n childController,\n );\n }\n } else {\n const { fn } = this.config;\n result = await this.executeWithTimeout(\n () => this.resolveHandlerResult(\n fn(handlerEvent),\n handlerEvent,\n ),\n handlerEvent.routerOptions,\n childController,\n );\n }\n } finally {\n if (cleanupParentListener) {\n cleanupParentListener();\n }\n }\n\n response = await toResponse(result, handlerEvent);\n\n if (response) {\n event.dispatched = true;\n }\n } catch (e) {\n event.error = isError(e) ? e : createError(e);\n\n await this.hookManager.trigger(HookName.ERROR, event);\n\n if (event.dispatched) {\n event.error = undefined;\n } else {\n throw event.error;\n }\n }\n\n await this.hookManager.trigger(HookName.CHILD_DISPATCH_AFTER, event);\n\n return response;\n }\n\n // --------------------------------------------------\n\n matchPath(path: string): boolean {\n if (!this.pathMatcher) {\n return true;\n }\n\n return this.pathMatcher.test(path);\n }\n\n // --------------------------------------------------\n\n /**\n * Resolve a handler's return value into the final value handed to `toResponse`.\n *\n * Contract:\n * - non-undefined value → return as-is (becomes the response)\n * - `undefined` + `event.next()` was called → forward downstream result\n * - `undefined` + `event.next()` not yet called → wait until either `next()` is\n * invoked (e.g. from an async callback) or `signal` aborts. A global or\n * per-handler timeout aborts `signal` and surfaces as 408. With no timeout\n * configured and no eventual `next()` call, the request hangs by design.\n */\n protected async resolveHandlerResult(\n invocation: unknown | Promise<unknown>,\n handlerEvent: IRoutupEvent,\n ): Promise<unknown> {\n const value = await invocation;\n if (typeof value !== 'undefined') {\n return value;\n }\n\n if (handlerEvent.nextCalled) {\n return handlerEvent.nextResult;\n }\n\n const { signal } = handlerEvent;\n\n if (signal.aborted) {\n throw createError({ status: 408, message: 'Request Timeout' });\n }\n\n return new Promise<unknown>((resolve, reject) => {\n const onAbort = () => {\n signal.removeEventListener('abort', onAbort);\n reject(createError({\n status: 408,\n message: 'Request Timeout',\n }));\n };\n\n signal.addEventListener('abort', onAbort, { once: true });\n\n handlerEvent.whenNextCalled().then(() => {\n signal.removeEventListener('abort', onAbort);\n resolve(handlerEvent.nextResult);\n });\n });\n }\n\n protected async executeWithTimeout(\n fn: () => unknown | Promise<unknown>,\n routerOptions: RouterOptions,\n controller?: AbortController,\n ): Promise<unknown> {\n const effectiveTimeout = this.resolveTimeout(routerOptions);\n\n if (!effectiveTimeout) {\n return fn();\n }\n\n let timerId: ReturnType<typeof setTimeout> | undefined;\n\n try {\n return await Promise.race([\n fn(),\n new Promise<never>((_, reject) => {\n timerId = setTimeout(() => {\n if (controller) {\n controller.abort();\n }\n reject(createError({\n status: 408,\n message: 'Request Timeout',\n }));\n }, effectiveTimeout);\n }),\n ]);\n } finally {\n clearTimeout(timerId);\n }\n }\n\n protected resolveTimeout(routerOptions: RouterOptions): number | undefined {\n const routerDefault = routerOptions.handlerTimeout;\n const handlerOverride = this.config.timeout;\n\n if (!routerDefault && !handlerOverride) {\n return undefined;\n }\n\n if (!routerDefault) {\n return handlerOverride;\n }\n\n if (!handlerOverride) {\n return routerDefault;\n }\n\n if (routerOptions.handlerTimeoutOverridable) {\n return handlerOverride;\n }\n\n return Math.min(routerDefault, handlerOverride);\n }\n\n protected mountHooks() {\n if (this.config.onBefore) {\n this.hookManager.addListener(HookName.CHILD_DISPATCH_BEFORE, this.config.onBefore);\n }\n\n if (this.config.onAfter) {\n this.hookManager.addListener(HookName.CHILD_DISPATCH_AFTER, this.config.onAfter);\n }\n\n if (this.config.onError) {\n this.hookManager.addListener(HookName.ERROR, this.config.onError);\n }\n }\n}\n","import { HandlerType } from '../constants.ts';\nimport { Handler } from '../module.ts';\nimport type {\n CoreHandler,\n CoreHandlerOptions,\n} from './types.ts';\n\n/**\n * Create a request handler.\n *\n * @param input - Handler function `(event) => value` or options object `{ fn, path?, method? }`\n *\n * @example\n * ```typescript\n * // Shorthand — function only\n * router.get('/', defineCoreHandler((event) => 'Hello'));\n *\n * // Verbose — with path and method\n * router.use(defineCoreHandler({\n * path: '/users/:id',\n * method: 'GET',\n * fn: (event) => ({ id: event.params.id }),\n * }));\n * ```\n */\nexport function defineCoreHandler(input: Omit<CoreHandlerOptions, | 'type'>) : Handler;\n\nexport function defineCoreHandler(input: CoreHandler) : Handler;\n\nexport function defineCoreHandler(input: any) : Handler {\n if (typeof input === 'function') {\n return new Handler({\n type: HandlerType.CORE,\n fn: input,\n });\n }\n\n return new Handler({\n type: HandlerType.CORE,\n ...input,\n });\n}\n","import { HandlerType } from '../constants.ts';\nimport { Handler } from '../module.ts';\nimport type {\n ErrorHandler,\n ErrorHandlerOptions,\n} from './types.ts';\n\n/**\n * Create an error handler.\n *\n * Error handlers receive errors thrown by preceding handlers in the pipeline.\n *\n * @param input - Handler function `(error, event) => value` or options object `{ fn, path? }`\n *\n * @example\n * ```typescript\n * router.use(defineErrorHandler((error, event) => {\n * return { message: error.message };\n * }));\n * ```\n */\nexport function defineErrorHandler(input: Omit<ErrorHandlerOptions, 'type'>) : Handler;\n\nexport function defineErrorHandler(input: ErrorHandler) : Handler;\nexport function defineErrorHandler(input: any) : Handler {\n if (typeof input === 'function') {\n return new Handler({\n type: HandlerType.ERROR,\n fn: input,\n });\n }\n\n return new Handler({\n type: HandlerType.ERROR,\n ...input,\n });\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { IRoutupEvent } from '../../../event/index.ts';\nimport { RoutupError } from '../../../error/module.ts';\nimport { defineCoreHandler } from '../../core/index.ts';\nimport type { Handler } from '../../module.ts';\nimport type { CoreHandler } from '../../core/types.ts';\nimport type { NodeHandler, NodeMiddleware } from './types.ts';\n\nconst kHandled = /* @__PURE__ */ Symbol('handled');\n\nfunction callHandler(\n handler: NodeHandler,\n req: IncomingMessage,\n res: ServerResponse,\n): Promise<typeof kHandled | void> {\n return new Promise((resolve, reject) => {\n let settled = false;\n\n const onClose = () => settle(kHandled);\n const onFinish = () => settle(kHandled);\n const onError = (error: Error) => fail(error);\n\n function cleanup() {\n res.removeListener('close', onClose);\n res.removeListener('finish', onFinish);\n res.removeListener('error', onError);\n }\n\n function settle(value: typeof kHandled | void) {\n if (settled) return;\n settled = true;\n cleanup();\n resolve(value);\n }\n\n function fail(error: unknown) {\n if (settled) return;\n settled = true;\n cleanup();\n reject(error);\n }\n\n res.once('close', onClose);\n res.once('finish', onFinish);\n res.once('error', onError);\n\n try {\n Promise.resolve(handler(req, res))\n .then(() => settle(kHandled))\n .catch(fail);\n } catch (error) {\n fail(error);\n }\n });\n}\n\nfunction callMiddleware(\n handler: NodeMiddleware,\n req: IncomingMessage,\n res: ServerResponse,\n): Promise<typeof kHandled | void> {\n return new Promise((resolve, reject) => {\n let settled = false;\n\n const onClose = () => settle(kHandled);\n const onFinish = () => settle(kHandled);\n const onError = (error: Error) => fail(error);\n\n function cleanup() {\n res.removeListener('close', onClose);\n res.removeListener('finish', onFinish);\n res.removeListener('error', onError);\n }\n\n function settle(value: typeof kHandled | void) {\n if (settled) return;\n settled = true;\n cleanup();\n resolve(value);\n }\n\n function fail(error: unknown) {\n if (settled) return;\n settled = true;\n cleanup();\n reject(error);\n }\n\n res.once('close', onClose);\n res.once('finish', onFinish);\n res.once('error', onError);\n\n try {\n Promise.resolve(\n handler(req, res, (error) => {\n if (error) {\n fail(error);\n } else {\n settle(res.writableEnded || res.destroyed ? kHandled : undefined);\n }\n }),\n ).catch(fail);\n } catch (error) {\n fail(error);\n }\n });\n}\n\nfunction createNodeBridge(handler: NodeHandler | NodeMiddleware, isMiddleware: boolean): Handler {\n if (typeof handler !== 'function') {\n throw new RoutupError('fromNodeHandler/fromNodeMiddleware expects a function.');\n }\n\n return defineCoreHandler({\n fn: (async (event: IRoutupEvent) => {\n const node = event.request.runtime?.node;\n if (!node?.req || !node?.res) {\n throw new RoutupError('fromNodeHandler/fromNodeMiddleware requires a Node.js runtime.');\n }\n\n const req = node.req as unknown as IncomingMessage;\n const res = node.res as unknown as ServerResponse;\n\n const result = isMiddleware ?\n await callMiddleware(handler as NodeMiddleware, req, res) :\n await callHandler(handler as NodeHandler, req, res);\n\n if (result === kHandled) {\n return null;\n }\n\n return event.next();\n }) as CoreHandler,\n });\n}\n\n/**\n * Wraps a Node.js `(req, res)` handler for use in the routup pipeline.\n *\n * @example\n * ```typescript\n * import { fromNodeHandler } from 'routup/node';\n *\n * router.use(fromNodeHandler((req, res) => {\n * res.end('Hello');\n * }));\n * ```\n */\nexport function fromNodeHandler(handler: NodeHandler): Handler {\n return createNodeBridge(handler, false);\n}\n\n/**\n * Wraps a Node.js `(req, res, next)` middleware for use in the routup pipeline.\n *\n * @example\n * ```typescript\n * import cors from 'cors';\n * import { fromNodeMiddleware } from 'routup/node';\n *\n * router.use(fromNodeMiddleware(cors()));\n * ```\n */\nexport function fromNodeMiddleware(handler: NodeMiddleware): Handler {\n return createNodeBridge(handler, true);\n}\n","import { isObject } from '../../../utils/index.ts';\nimport type { WebHandler, WebHandlerProvider } from './types.ts';\n\nexport function isWebHandlerProvider(input: unknown): input is WebHandlerProvider {\n return isObject(input) &&\n typeof input.fetch === 'function';\n}\n\nexport function isWebHandler(input: unknown): input is WebHandler {\n return typeof input === 'function';\n}\n","import type { IRoutupEvent } from '../../../event/index.ts';\nimport { RoutupError } from '../../../error/index.ts';\nimport { defineCoreHandler } from '../../core/index.ts';\nimport type { Handler } from '../../module.ts';\nimport { isWebHandlerProvider } from './is.ts';\nimport type { WebHandler, WebHandlerProvider } from './types.ts';\n\n/**\n * Create a handler from a Web Fetch API-compatible function or object.\n *\n * Wraps an external app (e.g. Hono, another Router) so it can be mounted\n * via `router.use()`. The original request is passed through as-is.\n *\n * @param input - Fetch function `(request) => Response` or object with a `fetch` method\n *\n * @experimental\n *\n * @example\n * ```ts\n * // Mount an object with a fetch method\n * router.use('/api', fromWebHandler(honoApp));\n *\n * // Mount a plain fetch function\n * router.use('/proxy', fromWebHandler((req) => fetch(req)));\n * ```\n */\nexport function fromWebHandler(input: WebHandler) : Handler;\n\nexport function fromWebHandler(input: WebHandlerProvider) : Handler;\n\nexport function fromWebHandler(input: any) : Handler {\n if (isWebHandlerProvider(input)) {\n return fromWebHandler(input.fetch.bind(input));\n }\n\n if (typeof input !== 'function') {\n throw new RoutupError('fromWebHandler expects a function or an object with a fetch method.');\n }\n\n return defineCoreHandler({ fn: (event: IRoutupEvent) => input(event.request) });\n}\n","import { isInstance, isObject } from '../utils/index.ts';\nimport { HandlerSymbol } from './constants.ts';\nimport type { Handler } from './module.ts';\nimport type { HandlerOptions } from './types.ts';\n\nexport function isHandlerOptions(input: unknown) : input is HandlerOptions {\n return isObject(input) &&\n typeof input.fn === 'function' &&\n typeof input.type === 'string';\n}\n\nexport function isHandler(input: unknown): input is Handler {\n return isInstance(input, HandlerSymbol);\n}\n\n","import { HeaderName } from '../../constants.ts';\n\nimport type { IRoutupEvent } from '../../event/index.ts';\n\nexport function isRequestCacheable(event: IRoutupEvent, modifiedTime: string | Date) : boolean {\n const modifiedSince = event.headers.get(HeaderName.IF_MODIFIED_SINCE);\n if (!modifiedSince) {\n return false;\n }\n\n modifiedTime = typeof modifiedTime === 'string' ?\n new Date(modifiedTime) :\n modifiedTime;\n\n const sinceDate = new Date(modifiedSince);\n if (Number.isNaN(sinceDate.getTime()) || Number.isNaN(modifiedTime.getTime())) {\n return false;\n }\n\n return sinceDate >= modifiedTime;\n}\n","import type { IRoutupEvent } from '../../event/index.ts';\nimport { useRequestNegotiator } from './negotiator.ts';\n\nexport function getRequestAcceptableCharsets(event: IRoutupEvent) : string[] {\n const negotiator = useRequestNegotiator(event);\n\n return negotiator.charsets();\n}\n\nexport function getRequestAcceptableCharset(event: IRoutupEvent, input: string | string[]) : string | undefined {\n input = input || [];\n\n const items = Array.isArray(input) ? input : [input];\n\n if (items.length === 0) {\n return getRequestAcceptableCharsets(event).shift();\n }\n\n const negotiator = useRequestNegotiator(event);\n return negotiator.charsets(items).shift() || undefined;\n}\n","import type { IRoutupEvent } from '../../event/index.ts';\nimport { useRequestNegotiator } from './negotiator.ts';\n\nexport function getRequestAcceptableEncodings(event: IRoutupEvent) : string[] {\n const negotiator = useRequestNegotiator(event);\n return negotiator.encodings();\n}\n\nexport function getRequestAcceptableEncoding(event: IRoutupEvent, input: string | string[]) : string | undefined {\n input = input || [];\n\n const items = Array.isArray(input) ? input : [input];\n\n if (items.length === 0) {\n return getRequestAcceptableEncodings(event).shift();\n }\n\n const negotiator = useRequestNegotiator(event);\n return negotiator.encodings(items).shift() || undefined;\n}\n","import type { IRoutupEvent } from '../../event/index.ts';\nimport { useRequestNegotiator } from './negotiator.ts';\n\nexport function getRequestAcceptableLanguages(event: IRoutupEvent) : string[] {\n const negotiator = useRequestNegotiator(event);\n return negotiator.languages();\n}\n\nexport function getRequestAcceptableLanguage(event: IRoutupEvent, input?: string | string[]) : string | undefined {\n input = input || [];\n\n const items = Array.isArray(input) ? input : [input];\n\n if (items.length === 0) {\n return getRequestAcceptableLanguages(event).shift();\n }\n\n const negotiator = useRequestNegotiator(event);\n return negotiator.languages(items).shift() || undefined;\n}\n","import { HeaderName } from '../../constants.ts';\nimport { getMimeType } from '../../utils/index.ts';\nimport type { IRoutupEvent } from '../../event/index.ts';\nimport { getRequestHeader } from './header.ts';\n\nexport function matchRequestContentType(event: IRoutupEvent, contentType: string) : boolean {\n const header = getRequestHeader(event, HeaderName.CONTENT_TYPE);\n if (!header) {\n return true;\n }\n\n return header.split(';')[0]!.trim() === getMimeType(contentType);\n}\n","import { HeaderName } from '../../constants.ts';\nimport type { TrustProxyFn, TrustProxyInput } from '../../utils/index.ts';\nimport { buildTrustProxyFn } from '../../utils/index.ts';\nimport type { IRoutupEvent } from '../../event/index.ts';\n\nexport type RequestHostNameOptions = {\n trustProxy?: TrustProxyInput,\n};\n\nexport function getRequestHostName(event: IRoutupEvent, options: RequestHostNameOptions = {}) : string | undefined {\n let trustProxy : TrustProxyFn;\n if (typeof options.trustProxy !== 'undefined') {\n trustProxy = buildTrustProxyFn(options.trustProxy);\n } else {\n trustProxy = event.routerOptions.trustProxy;\n }\n\n let hostname = event.headers.get(HeaderName.X_FORWARDED_HOST);\n if (!hostname || !event.request.ip || !trustProxy(event.request.ip, 0)) {\n hostname = event.headers.get(HeaderName.HOST);\n } else if (hostname && hostname.includes(',')) {\n hostname = hostname.substring(0, hostname.indexOf(',')).trimEnd();\n }\n\n if (!hostname) {\n return undefined;\n }\n\n // IPv6 literal support\n const offset = hostname[0] === '[' ?\n hostname.indexOf(']') + 1 :\n 0;\n const index = hostname.indexOf(':', offset);\n\n const result = index !== -1 ?\n hostname.substring(0, index) :\n hostname;\n\n // Reject hostnames with obviously invalid characters\n // eslint-disable-next-line no-control-regex\n if (/[\\x00-\\x1F\\x7F\\s/@\\\\]/.test(result)) {\n return undefined;\n }\n\n return result;\n}\n","import { HeaderName } from '../../constants.ts';\nimport type { IRoutupEvent } from '../../event/index.ts';\nimport type { TrustProxyFn, TrustProxyInput } from '../../utils/index.ts';\nimport { buildTrustProxyFn } from '../../utils/index.ts';\n\nexport type RequestIpOptions = {\n trustProxy?: TrustProxyInput,\n};\n\n/**\n * Get the client IP address from the request.\n *\n * When `trustProxy` is configured, walks the `X-Forwarded-For` chain\n * and returns the rightmost untrusted address (the actual client IP).\n * Falls back to `event.request.ip` (the direct connection IP).\n */\nexport function getRequestIP(event: IRoutupEvent, options: RequestIpOptions = {}) : string | undefined {\n let trustProxy : TrustProxyFn;\n if (typeof options.trustProxy !== 'undefined') {\n trustProxy = buildTrustProxyFn(options.trustProxy);\n } else {\n trustProxy = event.routerOptions.trustProxy;\n }\n\n const socketAddr = event.request.ip;\n if (!socketAddr) {\n return undefined;\n }\n\n // Build address list: [socket IP, ...forwarded addresses (rightmost first)]\n const forwarded = event.headers.get(HeaderName.X_FORWARDED_FOR);\n const addrs: string[] = [socketAddr];\n\n if (forwarded) {\n const parts = forwarded.split(',');\n for (let i = parts.length - 1; i >= 0; i--) {\n const addr = parts[i]!.trim();\n if (addr) {\n addrs.push(addr);\n }\n }\n }\n\n // Walk from socket (leftmost) to client (rightmost),\n // stopping at the first untrusted address\n for (let i = 0; i < addrs.length - 1; i++) {\n if (!trustProxy(addrs[i]!, i)) {\n return addrs[i];\n }\n }\n\n // All proxies trusted — return the original client (last in chain)\n return addrs[addrs.length - 1];\n}\n","import { HeaderName } from '../../constants.ts';\nimport type { TrustProxyFn, TrustProxyInput } from '../../utils/index.ts';\nimport { buildTrustProxyFn } from '../../utils/index.ts';\nimport type { IRoutupEvent } from '../../event/index.ts';\n\nexport type RequestProtocolOptions = {\n trustProxy?: TrustProxyInput,\n default?: string,\n};\n\nexport function getRequestProtocol(\n event: IRoutupEvent,\n options: RequestProtocolOptions = {},\n) : string {\n let trustProxy : TrustProxyFn;\n if (typeof options.trustProxy !== 'undefined') {\n trustProxy = buildTrustProxyFn(options.trustProxy);\n } else {\n trustProxy = event.routerOptions.trustProxy;\n }\n\n // Derive protocol from the request URL scheme\n let protocol : string;\n try {\n const url = new URL(event.request.url);\n if (url.protocol === 'https:') {\n protocol = 'https';\n } else {\n protocol = 'http';\n }\n } catch {\n protocol = options.default || 'http';\n }\n\n if (!event.request.ip || !trustProxy(event.request.ip, 0)) {\n return protocol;\n }\n\n const header = event.headers.get(HeaderName.X_FORWARDED_PROTO);\n if (!header) {\n return protocol;\n }\n\n const index = header.indexOf(',');\n\n const forwarded = index !== -1 ?\n header.substring(0, index).trim().toLowerCase() :\n header.trim().toLowerCase();\n\n if (forwarded === 'http' || forwarded === 'https') {\n return forwarded;\n }\n\n return protocol;\n}\n","export const PluginErrorCode = {\n PLUGIN: 'PLUGIN',\n NOT_INSTALLED: 'PLUGIN_NOT_INSTALLED',\n ALREADY_INSTALLED: 'PLUGIN_ALREADY_INSTALLED',\n INSTALL: 'PLUGIN_INSTALL',\n} as const;\n\nexport type PluginErrorCode = typeof PluginErrorCode[keyof typeof PluginErrorCode];\n","import { isError } from '../../error/is.ts';\nimport { PluginErrorCode } from './constants.ts';\nimport type { PluginError } from './module.ts';\n\nconst PLUGIN_ERROR_CODES = new Set<string>(Object.values(PluginErrorCode));\n\nexport function isPluginError(input: unknown): input is PluginError {\n if (!isError(input)) {\n return false;\n }\n\n return PLUGIN_ERROR_CODES.has(input.code);\n}\n","import type { HTTPErrorInput } from '@ebec/http';\nimport { RoutupError } from '../../error/module.ts';\nimport { PluginErrorCode } from './constants.ts';\n\nexport class PluginError extends RoutupError {\n constructor(input: HTTPErrorInput = {}) {\n const options = typeof input === 'string' ? { message: input } : { ...(input as object) };\n if (!('code' in options) || !(options as Record<string, unknown>).code) {\n (options as Record<string, unknown>).code = PluginErrorCode.PLUGIN;\n }\n super(options as HTTPErrorInput);\n this.name = 'PluginError';\n }\n}\n","import { PluginErrorCode } from '../constants.ts';\nimport { PluginError } from '../module.ts';\n\nexport class PluginAlreadyInstalledError extends PluginError {\n public readonly pluginName: string;\n\n constructor(pluginName: string) {\n super({\n message: `Plugin \"${pluginName}\" is already installed on this router.`,\n code: PluginErrorCode.ALREADY_INSTALLED,\n });\n this.name = 'PluginAlreadyInstalledError';\n this.pluginName = pluginName;\n }\n}\n","import { PluginErrorCode } from '../constants.ts';\nimport { PluginError } from '../module.ts';\n\nexport class PluginInstallError extends PluginError {\n public readonly pluginName: string;\n\n constructor(pluginName: string, cause?: Error) {\n super({\n message: `Failed to install plugin \"${pluginName}\".`,\n code: PluginErrorCode.INSTALL,\n cause,\n });\n this.name = 'PluginInstallError';\n this.pluginName = pluginName;\n }\n}\n","import { PluginErrorCode } from '../constants.ts';\nimport { PluginError } from '../module.ts';\n\nexport class PluginNotInstalledError extends PluginError {\n public readonly pluginName: string;\n\n public readonly helperName: string;\n\n constructor(pluginName: string, helperName: string) {\n super({\n message: `${helperName}() requires the \"${pluginName}\" plugin. ` +\n `Register it with: router.use(${pluginName}())`,\n code: PluginErrorCode.NOT_INSTALLED,\n });\n this.name = 'PluginNotInstalledError';\n this.pluginName = pluginName;\n this.helperName = helperName;\n }\n}\n","import { isObject } from '../utils/index.ts';\nimport type { Plugin } from './types.ts';\n\nexport function isPlugin(input: unknown): input is Plugin {\n if (!isObject(input)) {\n return false;\n }\n\n if (\n typeof input.name !== 'undefined' &&\n typeof input.name !== 'string'\n ) {\n return false;\n }\n\n return typeof input.install === 'function' &&\n input.install.length === 1;\n}\n","import { buildEtagFn, buildTrustProxyFn } from '../utils/index.ts';\nimport type { RouterOptions, RouterOptionsInput } from './types.ts';\n\nexport function normalizeRouterOptions(input: RouterOptionsInput): Partial<RouterOptions> {\n if (typeof input.etag !== 'undefined') {\n input.etag = buildEtagFn(input.etag);\n }\n\n if (typeof input.trustProxy !== 'undefined') {\n input.trustProxy = buildTrustProxyFn(input.trustProxy);\n }\n\n if (typeof input.timeout !== 'undefined') {\n if (\n typeof input.timeout !== 'number' ||\n !Number.isFinite(input.timeout) ||\n input.timeout <= 0\n ) {\n delete input.timeout;\n }\n }\n\n if (typeof input.handlerTimeout !== 'undefined') {\n if (\n typeof input.handlerTimeout !== 'number' ||\n !Number.isFinite(input.handlerTimeout) ||\n input.handlerTimeout <= 0\n ) {\n delete input.handlerTimeout;\n }\n }\n\n return input as Partial<RouterOptions>;\n}\n","export const RouterSymbol = Symbol.for('Router');\n\nexport const RouterPipelineStep = {\n START: 0,\n LOOKUP: 1,\n CHILD_BEFORE: 2,\n CHILD_DISPATCH: 3,\n CHILD_AFTER: 4,\n FINISH: 5,\n} as const;\n\nexport type RouterPipelineStep = typeof RouterPipelineStep[keyof typeof RouterPipelineStep];\n\nexport const RouterStackEntryType = {\n ROUTER: 'router',\n HANDLER: 'handler',\n} as const;\n\n\nexport type RouterStackEntryType = typeof RouterStackEntryType[keyof typeof RouterStackEntryType];\n","import type { Path } from '../path/index.ts';\nimport { PathMatcher } from '../path/index.ts';\nimport { isInstance, withLeadingSlash, withoutTrailingSlash } from '../utils/index.ts';\nimport { RouterSymbol } from './constants.ts';\nimport type { Router } from './module.ts';\n\nexport function isRouterInstance(input: unknown): input is Router {\n return isInstance(input, RouterSymbol);\n}\n\n/**\n * Build a non-terminal `PathMatcher` for a router mount path.\n *\n * Returns `undefined` when the path is the root (`/`) or omitted entirely —\n * a router mounted at the root has no intrinsic path filter.\n */\nexport function buildRouterPathMatcher(value?: Path): PathMatcher | undefined {\n if (value === '/' || typeof value === 'undefined') {\n return undefined;\n }\n\n return new PathMatcher(\n withLeadingSlash(withoutTrailingSlash(`${value}`)),\n { end: false },\n );\n}\n\n/**\n * Check if the request accepts JSON responses.\n * Matches application/json and +json suffixes (e.g. application/vnd.api+json).\n * Returns true if no Accept header is present (API-first default).\n */\nexport function acceptsJson(request: Request): boolean {\n const accept = request.headers.get('accept');\n if (!accept) {\n return true;\n }\n\n return accept.includes('application/json') ||\n accept.includes('+json') ||\n accept.includes('*/*');\n}\n","import { HeaderName, MethodName } from '../constants.ts';\nimport { DispatcherEvent } from '../dispatcher/index.ts';\nimport type { IDispatcherEvent } from '../dispatcher/index.ts';\nimport type { RoutupRequest } from '../event/index.ts';\nimport { createError } from '../error/index.ts';\nimport {\n Handler,\n type HandlerOptions,\n HandlerType,\n buildHandlerPathMatcher,\n isHandler,\n isHandlerOptions,\n matchHandlerMethod,\n} from '../handler/index.ts';\nimport type {\n HookDefaultListener,\n HookErrorListener,\n HookListener,\n HookUnsubscribeFn,\n} from '../hook/index.ts';\nimport { HookManager, HookName } from '../hook/index.ts';\nimport type { Path, PathMatcher } from '../path/index.ts';\nimport { isPath } from '../path/index.ts';\nimport type { Plugin, PluginInstallContext } from '../plugin/index.ts';\nimport {\n PluginAlreadyInstalledError,\n isPlugin,\n} from '../plugin/index.ts';\nimport { normalizeRouterOptions } from './options.ts';\nimport {\n cleanDoubleSlashes,\n withLeadingSlash,\n} from '../utils/index.ts';\nimport { RouterPipelineStep, RouterStackEntryType, RouterSymbol } from './constants.ts';\nimport type {\n IRouter,\n RouterOptions,\n RouterOptionsInput,\n RouterPipelineContext,\n StackEntry,\n} from './types.ts';\nimport { acceptsJson, buildRouterPathMatcher, isRouterInstance } from './utils.ts';\n\nexport class Router implements IRouter {\n readonly '@instanceof' = RouterSymbol;\n\n /**\n * A label for the router instance.\n */\n readonly name?: string;\n\n /**\n * Array of mounted layers, routes & routers, each tagged by kind so the\n * dispatch loop can discriminate without `isRouterInstance`/`isHandler`\n * runtime checks.\n *\n * @protected\n */\n protected stack: StackEntry[] = [];\n\n /**\n * Path matcher for the current mount path.\n *\n * @protected\n */\n protected pathMatcher: PathMatcher | undefined;\n\n /**\n * A hook manager.\n *\n * @protected\n */\n protected hookManager: HookManager;\n\n /**\n * Normalized options for this router instance.\n */\n protected _options: Partial<RouterOptions>;\n\n /**\n * Registry of installed plugins (name → version) on this router.\n *\n * @protected\n */\n protected plugins: Map<string, string | undefined> = new Map();\n\n // --------------------------------------------------\n\n constructor(input: RouterOptionsInput = {}) {\n this.name = input.name;\n\n this.hookManager = new HookManager();\n this._options = normalizeRouterOptions(input);\n this.pathMatcher = buildRouterPathMatcher(input.path);\n }\n\n // --------------------------------------------------\n\n matchPath(path: string): boolean {\n if (this.pathMatcher) {\n return this.pathMatcher.test(path);\n }\n\n return true;\n }\n\n // --------------------------------------------------\n\n /**\n * Public entry point — creates a DispatcherEvent from the request,\n * runs the pipeline, and returns a Response (with 404/500 fallbacks).\n */\n async fetch(request: RoutupRequest): Promise<Response> {\n const event = new DispatcherEvent(request);\n\n let response: Response | undefined;\n\n try {\n const timeoutMs = this._options.timeout;\n\n if (timeoutMs) {\n const controller = new AbortController();\n event.signal = controller.signal;\n\n let timerId: ReturnType<typeof setTimeout> | undefined;\n\n try {\n response = await Promise.race([\n this.dispatch(event),\n new Promise<never>((_, reject) => {\n timerId = setTimeout(() => {\n controller.abort();\n reject(createError({\n status: 408,\n message: 'Request Timeout',\n }));\n }, timeoutMs);\n }),\n ]);\n } finally {\n clearTimeout(timerId);\n }\n } else {\n response = await this.dispatch(event);\n }\n } catch (e) {\n event.error = createError(e);\n }\n\n if (response) {\n return response;\n }\n\n if (event.error) {\n return this.buildFallbackResponse(\n request,\n event,\n event.error.status || 500,\n event.error.message,\n );\n }\n\n return this.buildFallbackResponse(request, event, 404, 'Not Found');\n }\n\n protected buildFallbackResponse(request: RoutupRequest, event: IDispatcherEvent, status: number, message: string): Response {\n const headers = new Headers(event.response.headers);\n\n if (acceptsJson(request)) {\n headers.set('content-type', 'application/json; charset=utf-8');\n return new Response(JSON.stringify({ status, message }), {\n status,\n headers,\n });\n }\n\n headers.set('content-type', 'text/plain; charset=utf-8');\n return new Response(message, {\n status,\n headers,\n });\n }\n\n // --------------------------------------------------\n\n protected async executePipelineStep(context: RouterPipelineContext): Promise<void> {\n while (context.step !== RouterPipelineStep.FINISH) {\n switch (context.step) {\n case RouterPipelineStep.START:\n await this.executePipelineStepStart(context); break;\n case RouterPipelineStep.LOOKUP:\n await this.executePipelineStepLookup(context); break;\n case RouterPipelineStep.CHILD_BEFORE:\n await this.executePipelineStepChildBefore(context); break;\n case RouterPipelineStep.CHILD_DISPATCH:\n await this.executePipelineStepChildDispatch(context); break;\n case RouterPipelineStep.CHILD_AFTER:\n await this.executePipelineStepChildAfter(context); break;\n default:\n context.step = RouterPipelineStep.FINISH; break;\n }\n }\n\n await this.executePipelineStepFinish(context);\n }\n\n protected async executePipelineStepStart(context: RouterPipelineContext): Promise<void> {\n await this.hookManager.trigger(HookName.REQUEST, context.event);\n\n if (context.event.dispatched) {\n context.step = RouterPipelineStep.FINISH;\n } else {\n context.step = RouterPipelineStep.LOOKUP;\n }\n }\n\n protected async executePipelineStepLookup(context: RouterPipelineContext): Promise<void> {\n while (\n !context.event.dispatched &&\n context.stackIndex < this.stack.length\n ) {\n const entry = this.stack[context.stackIndex]!;\n\n if (entry.type === RouterStackEntryType.HANDLER) {\n const handler = entry.data;\n\n if (\n (context.event.error && handler.type === HandlerType.CORE) ||\n (!context.event.error && handler.type === HandlerType.ERROR)\n ) {\n context.stackIndex++;\n continue;\n }\n\n const match = entry.pathMatcher ?\n entry.pathMatcher.test(context.event.path) :\n handler.matchPath(context.event.path);\n\n if (match) {\n const method = entry.method ?? handler.method;\n\n if (method) {\n context.event.methodsAllowed.add(method);\n }\n\n if (matchHandlerMethod(method, context.event.method as MethodName)) {\n await this.hookManager.trigger(HookName.CHILD_MATCH, context.event);\n\n if (context.event.dispatched) {\n context.step = RouterPipelineStep.FINISH;\n } else {\n context.step = RouterPipelineStep.CHILD_BEFORE;\n }\n\n return;\n }\n }\n\n context.stackIndex++;\n continue;\n }\n\n const match = entry.pathMatcher ?\n entry.pathMatcher.test(context.event.path) :\n entry.data.matchPath(context.event.path);\n\n if (match) {\n await this.hookManager.trigger(HookName.CHILD_MATCH, context.event);\n\n if (context.event.dispatched) {\n context.step = RouterPipelineStep.FINISH;\n } else {\n context.step = RouterPipelineStep.CHILD_BEFORE;\n }\n\n return;\n }\n\n context.stackIndex++;\n }\n\n context.step = RouterPipelineStep.FINISH;\n }\n\n protected async executePipelineStepChildBefore(context: RouterPipelineContext): Promise<void> {\n await this.hookManager.trigger(HookName.CHILD_DISPATCH_BEFORE, context.event);\n\n if (context.event.dispatched) {\n context.step = RouterPipelineStep.FINISH;\n } else {\n context.step = RouterPipelineStep.CHILD_DISPATCH;\n }\n }\n\n protected async executePipelineStepChildAfter(context: RouterPipelineContext): Promise<void> {\n await this.hookManager.trigger(HookName.CHILD_DISPATCH_AFTER, context.event);\n\n if (context.event.dispatched) {\n context.step = RouterPipelineStep.FINISH;\n } else {\n context.step = RouterPipelineStep.LOOKUP;\n }\n }\n\n protected async executePipelineStepChildDispatch(context: RouterPipelineContext): Promise<void> {\n const entry = this.stack[context.stackIndex];\n\n if (context.event.dispatched || typeof entry === 'undefined') {\n context.step = RouterPipelineStep.FINISH;\n return;\n }\n\n const { event } = context;\n\n // Snapshot routing state so we can restore it if the entry yields no\n // response. Without this, a child router that walks past its last\n // handler (e.g. its tail middleware calls next()) would leave the\n // event's path stripped of this entry's mount prefix, and subsequent\n // siblings in the parent's stack would fail to match.\n const savedPath = event.path;\n const savedMountPath = event.mountPath;\n const savedParams = event.params;\n\n if (entry.type === RouterStackEntryType.ROUTER && entry.pathMatcher) {\n // Router mount: strip the matched prefix off event.path so the\n // child router's pipeline sees a mount-relative path. The child\n // router's intrinsic pathMatcher (if any) is applied on top\n // inside its own dispatch.\n const output = entry.pathMatcher.exec(event.path);\n if (typeof output !== 'undefined') {\n event.mountPath = cleanDoubleSlashes(`${event.mountPath}/${output.path}`);\n\n if (event.path === output.path) {\n event.path = '/';\n } else {\n event.path = withLeadingSlash(event.path.substring(output.path.length));\n }\n\n event.params = {\n ...event.params,\n ...output.params,\n };\n }\n } else if (entry.type === RouterStackEntryType.HANDLER && entry.pathMatcher) {\n // Handler mount: extract route params from the mount matcher.\n // Handlers don't strip the path — they're leaves.\n const output = entry.pathMatcher.exec(event.path);\n if (typeof output !== 'undefined') {\n event.params = {\n ...event.params,\n ...output.params,\n };\n }\n }\n\n try {\n event.setNext(async (error?: Error) => {\n if (error) {\n event.error = createError(error);\n }\n\n // Continue pipeline from the next stack item\n const nextContext: RouterPipelineContext = {\n step: RouterPipelineStep.LOOKUP,\n event,\n stackIndex: context.stackIndex + 1,\n response: undefined,\n };\n\n await this.executePipelineStep(nextContext);\n\n return nextContext.response;\n });\n\n const response = await entry.data.dispatch(event);\n\n if (response) {\n context.response = response;\n event.dispatched = true;\n }\n } catch (e) {\n event.error = createError(e);\n\n await this.hookManager.trigger(HookName.ERROR, event);\n }\n\n if (!event.dispatched) {\n event.path = savedPath;\n event.mountPath = savedMountPath;\n event.params = savedParams;\n }\n\n context.stackIndex++;\n context.step = RouterPipelineStep.CHILD_AFTER;\n }\n\n protected async executePipelineStepFinish(context: RouterPipelineContext): Promise<void> {\n if (context.event.error || context.event.dispatched) {\n return this.hookManager.trigger(HookName.RESPONSE, context.event);\n }\n\n if (\n !context.event.dispatched &&\n context.event.routerPath.length === 1 &&\n context.event.method &&\n context.event.method === MethodName.OPTIONS\n ) {\n if (context.event.methodsAllowed.has(MethodName.GET)) {\n context.event.methodsAllowed.add(MethodName.HEAD);\n }\n\n const options = [...context.event.methodsAllowed]\n .map((key) => key.toUpperCase())\n .join(',');\n\n const optionsHeaders = new Headers(context.event.response.headers);\n optionsHeaders.set(HeaderName.ALLOW, options);\n context.response = new Response(options, {\n status: context.event.response.status || 200,\n headers: optionsHeaders,\n });\n\n context.event.dispatched = true;\n }\n\n return this.hookManager.trigger(HookName.RESPONSE, context.event);\n }\n\n // --------------------------------------------------\n\n async dispatch(\n event: IDispatcherEvent,\n ): Promise<Response | undefined> {\n const savedPath = event.path;\n const savedMountPath = event.mountPath;\n const savedParams = event.params;\n\n if (this.pathMatcher) {\n const output = this.pathMatcher.exec(event.path);\n if (typeof output !== 'undefined') {\n event.mountPath = cleanDoubleSlashes(`${event.mountPath}/${output.path}`);\n\n if (event.path === output.path) {\n event.path = '/';\n } else {\n event.path = withLeadingSlash(event.path.substring(output.path.length));\n }\n\n event.params = {\n ...event.params,\n ...output.params,\n };\n }\n }\n\n const context: RouterPipelineContext = {\n step: RouterPipelineStep.START,\n event,\n stackIndex: 0,\n };\n\n event.routerPath.push({ name: this.name, options: this._options });\n\n try {\n await this.executePipelineStep(context);\n } finally {\n event.routerPath.pop();\n\n // Restore routing state when this router did not produce a\n // response, so the caller's pipeline (a parent router) sees its\n // own pre-dispatch path/mountPath/params for subsequent siblings.\n if (!event.dispatched) {\n event.path = savedPath;\n event.mountPath = savedMountPath;\n event.params = savedParams;\n }\n }\n\n return context.response;\n }\n\n // --------------------------------------------------\n\n delete(...handlers: (Handler | HandlerOptions)[]): this;\n\n delete(path: Path, ...handlers: (Handler | HandlerOptions)[]): this;\n\n delete(...input: (Path | Handler | HandlerOptions)[]): this {\n this.useForMethod(MethodName.DELETE, ...input);\n\n return this;\n }\n\n get(...handlers: (Handler | HandlerOptions)[]): this;\n\n get(path: Path, ...handlers: (Handler | HandlerOptions)[]): this;\n\n get(...input: (Path | Handler | HandlerOptions)[]): this {\n this.useForMethod(MethodName.GET, ...input);\n\n return this;\n }\n\n post(...handlers: (Handler | HandlerOptions)[]): this;\n\n post(path: Path, ...handlers: (Handler | HandlerOptions)[]): this;\n\n post(...input: (Path | Handler | HandlerOptions)[]): this {\n this.useForMethod(MethodName.POST, ...input);\n\n return this;\n }\n\n put(...handlers: (Handler | HandlerOptions)[]): this;\n\n put(path: Path, ...handlers: (Handler | HandlerOptions)[]): this;\n\n put(...input: (Path | Handler | HandlerOptions)[]): this {\n this.useForMethod(MethodName.PUT, ...input);\n\n return this;\n }\n\n patch(...handlers: (Handler | HandlerOptions)[]): this;\n\n patch(path: Path, ...handlers: (Handler | HandlerOptions)[]): this;\n\n patch(...input: (Path | Handler | HandlerOptions)[]): this {\n this.useForMethod(MethodName.PATCH, ...input);\n\n return this;\n }\n\n head(...handlers: (Handler | HandlerOptions)[]): this;\n\n head(path: Path, ...handlers: (Handler | HandlerOptions)[]): this;\n\n head(...input: (Path | Handler | HandlerOptions)[]): this {\n this.useForMethod(MethodName.HEAD, ...input);\n\n return this;\n }\n\n options(...handlers: (Handler | HandlerOptions)[]): this;\n\n options(path: Path, ...handlers: (Handler | HandlerOptions)[]): this;\n\n options(...input: (Path | Handler | HandlerOptions)[]): this {\n this.useForMethod(MethodName.OPTIONS, ...input);\n\n return this;\n }\n\n // --------------------------------------------------\n\n protected useForMethod(\n method: MethodName,\n ...input: (Path | Handler | HandlerOptions)[]\n ) {\n let path: Path | undefined;\n\n for (const element of input) {\n if (isPath(element)) {\n path = element;\n continue;\n }\n\n let handler: Handler;\n if (isHandlerOptions(element)) {\n // Construct a fresh Handler from a copy of the options so the\n // user's options object is never mutated.\n handler = new Handler({\n ...element,\n method,\n path: path ?? element.path,\n });\n } else if (isHandler(element)) {\n handler = element;\n } else {\n continue;\n }\n\n this.stack.push({\n type: RouterStackEntryType.HANDLER,\n data: handler,\n method,\n pathMatcher: buildHandlerPathMatcher(path ?? handler.path, true),\n });\n }\n }\n\n // --------------------------------------------------\n\n use(router: Router): this;\n\n use(handler: Handler | HandlerOptions): this;\n\n use(plugin: Plugin): this;\n\n use(path: Path, router: Router): this;\n\n use(path: Path, handler: Handler | HandlerOptions): this;\n\n use(path: Path, plugin: Plugin): this;\n\n use(...input: unknown[]): this {\n let path: Path | undefined;\n for (const item of input) {\n if (isPath(item)) {\n path = withLeadingSlash(item);\n continue;\n }\n\n if (isRouterInstance(item)) {\n this.stack.push({\n type: RouterStackEntryType.ROUTER,\n data: item,\n pathMatcher: buildRouterPathMatcher(path),\n });\n continue;\n }\n\n if (isHandlerOptions(item)) {\n const handler = new Handler({\n ...item,\n path: path ?? item.path,\n });\n\n this.stack.push({\n type: RouterStackEntryType.HANDLER,\n data: handler,\n });\n continue;\n }\n\n if (isHandler(item)) {\n this.stack.push({\n type: RouterStackEntryType.HANDLER,\n data: item,\n pathMatcher: buildHandlerPathMatcher(path, !!item.method),\n });\n continue;\n }\n\n if (isPlugin(item)) {\n if (path) {\n this.install(item, { path });\n } else {\n this.install(item);\n }\n }\n }\n\n return this;\n }\n\n // --------------------------------------------------\n\n /**\n * Check if a plugin with the given name is installed on this router.\n */\n hasPlugin(name: string): boolean {\n return this.plugins.has(name);\n }\n\n /**\n * Get the version of an installed plugin by name on this router,\n * or `undefined` if the plugin is not installed here.\n */\n getPluginVersion(name: string): string | undefined {\n return this.plugins.get(name);\n }\n\n // --------------------------------------------------\n\n protected install(\n plugin: Plugin,\n context: PluginInstallContext = {},\n ): this {\n if (this.plugins.has(plugin.name)) {\n throw new PluginAlreadyInstalledError(plugin.name);\n }\n\n const router = new Router({ name: plugin.name });\n plugin.install(router);\n\n if (context.path) {\n this.use(context.path, router);\n } else {\n this.use(router);\n }\n\n this.plugins.set(plugin.name, plugin.version);\n\n return this;\n }\n\n //---------------------------------------------------------------------------------\n\n /**\n * Add a hook listener.\n *\n * @param name\n * @param fn\n */\n on(\n name: typeof HookName.REQUEST |\n typeof HookName.RESPONSE |\n typeof HookName.CHILD_DISPATCH_BEFORE |\n typeof HookName.CHILD_DISPATCH_AFTER,\n fn: HookDefaultListener,\n priority?: number,\n ): HookUnsubscribeFn;\n\n on(\n name: typeof HookName.CHILD_MATCH,\n fn: HookDefaultListener,\n priority?: number,\n ): HookUnsubscribeFn;\n\n on(\n name: typeof HookName.ERROR,\n fn: HookErrorListener,\n priority?: number,\n ): HookUnsubscribeFn;\n\n on(name: HookName, fn: HookListener, priority?: number): HookUnsubscribeFn {\n return this.hookManager.addListener(name, fn, priority);\n }\n\n /**\n * Remove single or all hook listeners.\n *\n * @param name\n */\n off(name: HookName): this;\n\n off(name: HookName, fn: HookListener): this;\n\n off(name: HookName, fn?: HookListener): this {\n if (typeof fn === 'undefined') {\n this.hookManager.removeListener(name);\n\n return this;\n }\n\n this.hookManager.removeListener(name, fn);\n return this;\n }\n}\n"],"mappings":"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"}
|