{"version":3,"file":"src-CA6xFXqy.mjs","names":[],"sources":["../src/cache/lru.ts","../src/constants.ts","../src/event/module.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/accepts-json.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/mime.ts","../src/utils/method.ts","../src/utils/path.ts","../src/utils/promise.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/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/error/is.ts","../src/error/create.ts","../src/response/to-response.ts","../src/dispatcher/module.ts","../src/handler/constants.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/handler/utils.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/path/matcher.ts","../src/path/utils.ts","../src/plugin/error/constants.ts","../src/plugin/error/is.ts","../src/plugin/error/module.ts","../src/plugin/error/sub/install.ts","../src/plugin/error/sub/not-installed.ts","../src/plugin/is.ts","../src/router/utils.ts","../src/router/linear/module.ts","../src/router/trie/parser.ts","../src/router/trie/node.ts","../src/router/trie/module.ts","../src/router/smart/module.ts","../src/app/options.ts","../src/app/constants.ts","../src/app/check.ts","../src/app/module.ts"],"sourcesContent":["import QuickLRU from 'quick-lru';\nimport type { ICache } from './types.ts';\n\nexport type LruCacheOptions = {\n    /**\n     * Maximum number of entries before the least-recently-used entry\n     * is evicted on `set`. Default: `1024`.\n     */\n    maxSize?: number;\n};\n\nconst DEFAULT_MAX_SIZE = 1024;\n\n/**\n * Default `ICache` implementation — a bounded LRU backed by\n * [`quick-lru`](https://github.com/sindresorhus/quick-lru). Picked for\n * its small footprint (~1kB), ESM-only build (matches routup), and\n * stable API.\n *\n * For TTL, size-based eviction, or dispose hooks, write your own\n * `ICache` (e.g. wrapping `lru-cache`) and pass it via the router's\n * `BaseRouterOptions.cache` slot.\n */\nexport class LruCache<V> implements ICache<V> {\n    protected inner: QuickLRU<string, V>;\n\n    constructor(options: LruCacheOptions = {}) {\n        this.inner = new QuickLRU<string, V>({ maxSize: options.maxSize ?? DEFAULT_MAX_SIZE });\n    }\n\n    get(key: string): V | undefined {\n        return this.inner.get(key);\n    }\n\n    set(key: string, value: V): void {\n        this.inner.set(key, value);\n    }\n\n    delete(key: string): void {\n        this.inner.delete(key);\n    }\n\n    clear(): void {\n        this.inner.clear();\n    }\n}\n","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\n/**\n * `MethodName` plus the open-enum escape hatch for non-standard\n * methods (`PROPFIND`, `MKCOL`, custom verbs). The `(string & {})`\n * intersection is structurally identical to `string` but TypeScript\n * doesn't collapse the union — so callers still get autocomplete\n * for the canonical methods while remaining free to pass anything.\n */\nexport type MethodNameLike = MethodName | (string & {});\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 { AppOptions } from '../app/types.ts';\nimport type { MethodNameLike } from '../constants.ts';\nimport type {\n    AppRequest,\n    AppResponse,\n    IAppEvent,\n} from './types.ts';\n\nexport type AppEventCreateContext = {\n    request: AppRequest;\n    params: Record<string, string | undefined>;\n    path: string;\n    method: MethodNameLike;\n    mountPath: string;\n    headers: Headers;\n    searchParams: URLSearchParams;\n    response: AppResponse;\n    store: Record<string | symbol, unknown>;\n    signal: AbortSignal;\n    appOptions: Readonly<AppOptions>;\n    next: (event: IAppEvent, error?: Error) => Promise<Response | undefined>;\n};\n\nexport class AppEvent implements IAppEvent {\n    readonly request: AppRequest;\n\n    readonly params: Record<string, string | undefined>;\n\n    readonly path: string;\n\n    readonly method: MethodNameLike;\n\n    readonly mountPath: string;\n\n    readonly headers: Headers;\n\n    readonly searchParams: URLSearchParams;\n\n    readonly response: AppResponse;\n\n    readonly store: Record<string | symbol, unknown>;\n\n    readonly signal: AbortSignal;\n\n    readonly appOptions: Readonly<AppOptions>;\n\n    protected _context: AppEventCreateContext;\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: AppEventCreateContext) {\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        this.appOptions = context.appOptions;\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 type { IAppEvent } from '../../event/index.ts';\n\nexport type ResponseCacheHeadersOptions = {\n    maxAge?: number,\n    modifiedTime?: string | Date,\n    cacheControls?: string[]\n};\n\nexport function setResponseCacheHeaders(event: IAppEvent, 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 { markInstanceof } from '@ebec/core';\nimport { HTTPError } from '@ebec/http';\nimport type { HTTPErrorInput } from '@ebec/http';\n\nexport type { HTTPErrorInput };\n\nexport const ErrorSymbol = Symbol.for('AppError');\n\nexport class AppError extends HTTPError {\n    constructor(input: HTTPErrorInput = {}) {\n        super(input);\n        this.name = 'AppError';\n        markInstanceof(this, ErrorSymbol);\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 { IAppEvent } from '../../../event/index.ts';\nimport { AppError } 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: IAppEvent,\n    options?: EventStreamOptions,\n): EventStreamHandle {\n    if (options?.maxMessageSize !== undefined) {\n        if (!Number.isInteger(options.maxMessageSize) || options.maxMessageSize < 0) {\n            throw new AppError('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","/**\n * Check if the request accepts JSON responses.\n *\n * Parses the `Accept` header per RFC 7231 (media ranges + quality\n * params) rather than substring-matching, so:\n * - `application/json-seq` does NOT count as accepting `application/json`\n * - `application/json;q=0` is treated as an explicit rejection\n *\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\n        .toLowerCase()\n        .split(',')\n        .some((entry) => {\n            const parts = entry.split(';').map((part) => part.trim());\n            const mediaRange = parts[0]!;\n            // Split each parameter on `=` and trim both halves so\n            // `q=0`, `q = 0`, and `q =0` are all recognized as q=0.\n            const qParam = parts.slice(1)\n                .map((param) => param.split('=').map((s) => s.trim()))\n                .find(([key]) => key === 'q');\n            const q = qParam ? Number.parseFloat(qParam[1] ?? '') : 1;\n            if (!Number.isFinite(q) || q <= 0) {\n                return false;\n            }\n\n            return mediaRange === '*/*' ||\n                mediaRange === 'application/*' ||\n                mediaRange === 'application/json' ||\n                mediaRange.endsWith('+json');\n        });\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","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\n/**\n * Default `EtagFn` used by `toResponse()` when `appOptions.etag` is\n * undefined. Module-scoped so we don't allocate per-request and so\n * all consumers share the same closure.\n *\n * `appOptions.etag === null` (explicitly disabled by the user)\n * remains distinct: consumers must check `=== undefined`, not\n * `== null`, before falling back to this default.\n */\nexport const DEFAULT_ETAG_FN: EtagFn = buildEtagFn();\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\n/**\n * Default `TrustProxyFn` used by request helpers when neither the\n * call's `options.trustProxy` nor `event.appOptions.trustProxy` is\n * set. Trusts no addresses — the conservative default.\n *\n * Module-scoped so all helpers share the same reference and we don't\n * allocate per-request.\n */\nexport const DEFAULT_TRUST_PROXY: TrustProxyFn = buildTrustProxyFn();\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","import { isObject } from './object.ts';\n\nexport function isPromise(p: unknown) : p is Promise<unknown> {\n    return isObject(p) &&\n        (\n            p instanceof Promise ||\n            // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n            // @ts-ignore\n            typeof p.then === 'function'\n        );\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\n/**\n * Concatenate path parts into a single mount path.\n *\n * - Drops `undefined` and empty parts.\n * - A lone `'/'` part still contributes (so `joinPaths('/')` returns\n *   `'/'`, distinguishing \"match the root exactly\" from \"no path\").\n * - Returns `undefined` when every part is missing — callers\n *   interpret this as \"no path\" (always-match middleware).\n * - Joins remaining parts with `/`, normalizes the leading slash,\n *   collapses any inner `//`, and trims a trailing slash on results\n *   longer than `/`.\n *\n * Used at registration time to fold a handler / router's intrinsic\n * path into the mount path so the active `IRouter` is the\n * only place that builds path matchers.\n */\nexport function joinPaths(...parts: Array<string | undefined>): string | undefined {\n    const kept: string[] = [];\n    for (const part of parts) {\n        if (typeof part !== 'string' || part === '') {\n            continue;\n        }\n        kept.push(part);\n    }\n    if (kept.length === 0) {\n        return undefined;\n    }\n    const normalized = cleanDoubleSlashes(withLeadingSlash(kept.join('/')));\n    if (normalized.length > 1 && normalized.endsWith('/')) {\n        return normalized.slice(0, -1);\n    }\n    return normalized;\n}\n","import { sanitizeHeaderValue } from '../../utils/index.ts';\nimport type { IAppEvent } from '../../event/index.ts';\n\nexport function appendResponseHeader(\n    event: IAppEvent,\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: IAppEvent,\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 { IAppEvent } from '../../event/index.ts';\n\nexport function setResponseContentTypeByFileName(event: IAppEvent, 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 { IAppEvent } 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: IAppEvent,\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: IAppEvent, filename?: string) {\n    setDisposition(event, 'attachment', filename);\n}\n\nexport function setResponseHeaderInline(event: IAppEvent, filename?: string) {\n    setDisposition(event, 'inline', filename);\n}\n","import { HeaderName } from '../../constants.ts';\nimport { getMimeType } from '../../utils/index.ts';\nimport type { IAppEvent } from '../../event/index.ts';\n\nexport function setResponseHeaderContentType(event: IAppEvent, 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 { HeaderName } from '../../constants.ts';\nimport { basename } from '../../utils/index.ts';\nimport type { IAppEvent } 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: IAppEvent,\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 { IAppEvent } from '../../event/index.ts';\n\nexport function getRequestHeader(\n    event: IAppEvent,\n    name: string,\n) : string | null {\n    return event.headers.get(name);\n}\n","import Negotiator from 'negotiator';\n\nimport type { IAppEvent } 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: IAppEvent) : 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 { IAppEvent } from '../../event/index.ts';\nimport { getRequestHeader } from './header.ts';\nimport { useRequestNegotiator } from './negotiator.ts';\n\nexport function getRequestAcceptableContentTypes(event: IAppEvent) : string[] {\n    const negotiator = useRequestNegotiator(event);\n\n    return negotiator.mediaTypes();\n}\n\nexport function getRequestAcceptableContentType(event: IAppEvent, 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 { IAppEvent } 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: IAppEvent, 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 { AppError } from '../../error/module.ts';\nimport { sanitizeHeaderValue } from '../../utils/index.ts';\nimport type { IAppEvent } from '../../event/index.ts';\n\nfunction escapeHtml(str: string) : string {\n    return str\n        .replace(/&/g, '&amp;')\n        .replace(/</g, '&lt;')\n        .replace(/>/g, '&gt;')\n        .replace(/\"/g, '&quot;');\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: IAppEvent, location: string, statusCode = 302): Response {\n    if (!isAllowedRedirectUrl(location)) {\n        throw new AppError({\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 { IAppEvent } from '../../event/index.ts';\n\nexport function sendStream(event: IAppEvent, 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 { hasInstanceof } from '@ebec/core';\nimport type { AppError } from './module.ts';\nimport { ErrorSymbol } from './module.ts';\n\nexport function isError(input: unknown) : input is AppError {\n    return hasInstanceof(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 { AppError } 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 AppError (returned as-is)\n * - an HTTPError (wrapped into a AppError 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) : AppError {\n    if (isError(input)) {\n        return input;\n    }\n\n    if (typeof input === 'string') {\n        return new AppError(input);\n    }\n\n    if (isHTTPError(input)) {\n        return new AppError({\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 AppError({\n            message: input.message,\n            cause: input,\n        });\n    }\n\n    if (!isObject(input)) {\n        return new AppError();\n    }\n\n    const options = { ...input as Record<string, unknown> };\n    if (options.cause === undefined) {\n        options.cause = input;\n    }\n\n    return new AppError(options as HTTPErrorInput);\n}\n\n","import { createError } from '../error/create.ts';\nimport type { IAppEvent } from '../event/index.ts';\nimport { DEFAULT_ETAG_FN } from '../utils/etag/utils.ts';\nimport type { EtagFn } from '../utils/etag/types.ts';\n\nfunction stripWeakPrefix(etag: string): string {\n    return etag.startsWith('W/') ? etag.slice(2) : etag;\n}\n\n/**\n * Resolve the effective etag fn for this request. `null` means the\n * user explicitly disabled ETag; `undefined` means the option was\n * never set, and we apply the framework default. Anything else is the\n * user's own fn.\n */\nfunction effectiveEtagFn(event: IAppEvent): EtagFn | null {\n    const opt = event.appOptions.etag;\n    if (opt === null) return null;\n    if (typeof opt === 'undefined') return DEFAULT_ETAG_FN;\n    return opt;\n}\n\n/**\n * Compute an ETag and conditionally return a 304, or set the header and\n * return undefined to let the caller emit the full response. Always\n * async because the ETag generator may be async (and typically is, via\n * `uncrypto`).\n */\nasync function applyEtag(\n    body: string,\n    event: IAppEvent,\n    headers: Headers,\n): Promise<Response | undefined> {\n    // The `null` short-circuit is handled by the caller so this\n    // function isn't even invoked on the hot path.\n    const etagFn = effectiveEtagFn(event);\n    if (!etagFn) {\n        return undefined;\n    }\n\n    const etag = await etagFn(body);\n    if (!etag) {\n        return undefined;\n    }\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\n/**\n * Convert a handler's return value into a Web `Response`.\n *\n * Returns synchronously for the common cases (string, JSON object,\n * binary, stream, blob) when ETag generation is disabled. Returns a\n * `Promise` when an ETag must be computed (the generator is async).\n *\n * Callers that want the async return uniformly can `await` the result\n * — `await` on a non-Promise still works but pays a microtask hop.\n * The App fast path branches on `instanceof Promise` to keep the\n * sync return truly sync.\n */\nexport function toResponse(\n    value: unknown,\n    event: IAppEvent,\n): Response | undefined | Promise<Response | undefined> {\n    // Cheap nullish checks first.\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    // typeof gate avoids running `instanceof` against every Web\n    // class for the common JSON-object case. Strings and primitives\n    // (number/boolean) take their dedicated branches; objects fall\n    // through to a single `instanceof Response` check + JSON.\n    const t = typeof value;\n\n    if (t === 'string') {\n        const { status, headers } = event.response;\n        if (!headers.has('content-type')) {\n            headers.set('content-type', 'text/plain; charset=utf-8');\n        }\n\n        // null is \"explicitly disabled\"; undefined falls back to the\n        // default fn. Either truthy fn or undefined → run applyEtag.\n        if (event.appOptions.etag !== null) {\n            return applyEtag(value as string, event, headers)\n                .then((cached) => cached ?? new Response(value as string, {\n                    status,\n                    headers,\n                }));\n        }\n\n        return new Response(value as string, {\n            status,\n            headers,\n        });\n    }\n\n    if (\n        t === 'object' &&\n        !Array.isArray(value)\n    ) {\n        // The handler's return value is structurally an object.\n        // Order checks by frequency: Response > JSON object > rare\n        // binary types. The hot path (JSON object) takes exactly\n        // one `instanceof Response` check before reaching the JSON\n        // serializer.\n        if (value instanceof Response) {\n            return value;\n        }\n\n        const { status, headers } = event.response;\n\n        // Binary / streaming bodies. Each branch is a single\n        // instanceof + dedicated Response construction.\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\n    const { status, headers } = event.response;\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    if (event.appOptions.etag !== null) {\n        return applyEtag(json, event, headers)\n            .then((cached) => cached ?? new Response(json, {\n                status,\n                headers,\n            }));\n    }\n\n    return new Response(json, {\n        status,\n        headers,\n    });\n}\n","import { FastURL } from 'srvx';\nimport type { AppError } from '../error/module.ts';\nimport { AppEvent } from '../event/module.ts';\nimport type {\n    AppRequest,\n    AppResponse,\n    IAppEvent,\n    NextFn,\n} from '../event/types.ts';\nimport { toResponse } from '../response/index.ts';\nimport type { AppOptions } from '../app/types.ts';\nimport type { MethodNameLike } from '../constants.ts';\nimport type { IDispatcherEvent } from './types.ts';\n\n\nexport class DispatcherEvent implements IDispatcherEvent {\n    readonly request: AppRequest;\n\n    params: Record<string, string | undefined>;\n\n    path: string;\n\n    readonly method: MethodNameLike;\n\n    /**\n     * Collected allowed methods (for OPTIONS).\n     */\n    methodsAllowed: Set<string>;\n\n    mountPath: string;\n\n    error?: AppError;\n\n    /**\n     * Options of the App currently dispatching this event. Set on\n     * entry to `App.dispatch` and restored on exit so re-entrant\n     * dispatch calls leave the caller's view intact. Initialized to\n     * `{}` so consumers reading before any dispatch get a valid\n     * (empty) shape.\n     */\n    appOptions: Readonly<AppOptions>;\n\n    /**\n     * `true` while an `App.dispatch` call is on the stack for this\n     * event. `App.dispatch` reads this on entry to derive `isRoot`\n     * and writes it on entry/exit so re-entrant calls behave\n     * correctly.\n     */\n    isDispatching: boolean;\n\n    protected _dispatched: boolean;\n\n    protected _response?: AppResponse;\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: IAppEvent, 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: AppRequest) {\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.appOptions = {};\n        this.isDispatching = false;\n        this.methodsAllowed = new Set();\n        this._dispatched = false;\n        this._nextCalled = false;\n    }\n\n    // ------------------------------------------------------------------------\n\n    get response(): AppResponse {\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: IAppEvent, 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): AppEvent {\n        return new AppEvent({\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            appOptions: this.appOptions,\n            next: (event: IAppEvent, 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","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","import { markInstanceof } from '@ebec/core';\nimport type { MethodName } from '../constants.ts';\nimport type { IDispatcher, IDispatcherEvent } from '../dispatcher/index.ts';\nimport { createError, isError } from '../error/index.ts';\nimport type { IAppEvent } from '../event/index.ts';\nimport { toResponse } from '../response/index.ts';\nimport type { AppOptions } from '../app/types.ts';\nimport { isPromise, toMethodName, withLeadingSlash } from '../utils/index.ts';\nimport { HandlerSymbol, HandlerType } from './constants.ts';\nimport type { HandlerOptions } from './types.ts';\n\nexport class Handler implements IDispatcher {\n    protected config: HandlerOptions;\n\n    readonly method: MethodName | undefined;\n\n    // --------------------------------------------------\n\n    constructor(handler: HandlerOptions) {\n        this.config = handler;\n\n        if (typeof handler.path === 'string') {\n            this.config.path = withLeadingSlash(handler.path);\n        }\n\n        this.method = this.config.method ? toMethodName(this.config.method) : undefined;\n\n        markInstanceof(this, HandlerSymbol);\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        let response: Response | undefined;\n        // Hoisted so the outer catch can forward it to `onError` and\n        // so the outer finally can release the parent-signal abort\n        // listener even when `onBefore` / `event.build()` throws —\n        // the inner try/finally that used to own this cleanup was\n        // unreachable from those throw sites.\n        let handlerEvent: IAppEvent | undefined;\n        let cleanupParentListener: (() => void) | undefined;\n\n        try {\n            // Read router options directly from the dispatcher event so we\n            // can decide on the per-handler timeout without first wrapping\n            // into a AppEvent — saves a `build()` allocation on the\n            // common no-timeout path.\n            const effectiveTimeout = this.resolveTimeout(event.appOptions);\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\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\n            // Build the handler event exactly once — with the child signal\n            // when a timeout is configured, otherwise inheriting the\n            // dispatcher's own signal.\n            handlerEvent = childController ?\n                event.build(childController.signal) :\n                event.build();\n\n            // ERROR handlers with no pending error are a no-op — and\n            // the onBefore/onAfter callbacks are too (no `fn` ran, so\n            // there's nothing to bracket).\n            const skipFn = this.config.type === HandlerType.ERROR && !event.error;\n\n            if (!skipFn && this.config.onBefore) {\n                await this.config.onBefore(handlerEvent);\n            }\n\n            let invocation: unknown;\n            if (skipFn) {\n                // invocation stays undefined; falls through to toResponse(undefined) → undefined.\n            } else if (this.config.type === HandlerType.ERROR) {\n                const { fn } = this.config;\n                invocation = fn(event.error!, handlerEvent);\n            } else {\n                const { fn } = this.config;\n                invocation = fn(handlerEvent);\n            }\n\n            let result: unknown;\n            if (skipFn) {\n                // no-op\n            } else if (effectiveTimeout) {\n                // Race the (possibly-async) invocation against the timeout.\n                result = await this.executeWithTimeout(\n                    () => this.resolveHandlerResult(invocation, handlerEvent!),\n                    effectiveTimeout,\n                    childController,\n                );\n            } else if (isPromise(invocation)) {\n                // Async handler return — await once. If it resolves\n                // to undefined, fall back to the async resolver\n                // (waits for `next()` or abort).\n                const awaited = await invocation;\n\n                result = typeof awaited === 'undefined' ?\n                    await this.resolveHandlerResult(undefined, handlerEvent) :\n                    awaited;\n            } else if (typeof invocation === 'undefined') {\n                // Sync undefined: defer to async resolver — handler\n                // may invoke `next()` later from a callback.\n                result = await this.resolveHandlerResult(undefined, handlerEvent);\n            } else {\n                // Sync non-undefined: zero internal microtasks.\n                result = invocation;\n            }\n\n            // `toResponse` returns sync when no ETag is configured —\n            // avoid an unconditional `await` to save a microtask.\n            const toResp = toResponse(result, handlerEvent);\n            response = isPromise(toResp) ?\n                await toResp :\n                toResp;\n\n            if (response) {\n                event.dispatched = true;\n                // ERROR handler resolved the pending error — clear it\n                // so parent pipelines don't observe a stale error.\n                if (this.config.type === HandlerType.ERROR && event.error) {\n                    event.error = undefined;\n                }\n            }\n\n            if (!skipFn && this.config.onAfter) {\n                await this.config.onAfter(handlerEvent, response);\n            }\n        } catch (e) {\n            event.error = isError(e) ? e : createError(e);\n\n            // Fire `onError` even if the error came from `onBefore`\n            // or `onAfter` — it is the handler-scoped error hook.\n            // `event.build()` is the fallback when the throw landed\n            // before we built `handlerEvent`.\n            if (this.config.onError) {\n                try {\n                    await this.config.onError(event.error, handlerEvent ?? event.build());\n                } catch (innerErr) {\n                    event.error = isError(innerErr) ? innerErr : createError(innerErr);\n                }\n            }\n\n            throw event.error;\n        } finally {\n            if (cleanupParentListener) {\n                cleanupParentListener();\n            }\n        }\n\n        return response;\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: IAppEvent,\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        effectiveTimeout: number | undefined,\n        controller?: AbortController,\n    ): Promise<unknown> {\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(appOptions: AppOptions): number | undefined {\n        const routerDefault = appOptions.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 (appOptions.handlerTimeoutOverridable) {\n            return handlerOverride;\n        }\n\n        return Math.min(routerDefault, handlerOverride);\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 { IAppEvent } from '../../../event/index.ts';\nimport { AppError } 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 AppError('fromNodeHandler/fromNodeMiddleware expects a function.');\n    }\n\n    return defineCoreHandler({\n        fn: (async (event: IAppEvent) => {\n            const node = event.request.runtime?.node;\n            if (!node?.req || !node?.res) {\n                throw new AppError('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 { IAppEvent } from '../../../event/index.ts';\nimport { AppError } 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 App) 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 AppError('fromWebHandler expects a function or an object with a fetch method.');\n    }\n\n    return defineCoreHandler({ fn: (event: IAppEvent) => input(event.request) });\n}\n","import { hasInstanceof } from '@ebec/core';\nimport { 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 hasInstanceof(input, HandlerSymbol);\n}\n\n","import { MethodName } from '../constants.ts';\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 { HeaderName } from '../../constants.ts';\n\nimport type { IAppEvent } from '../../event/index.ts';\n\nexport function isRequestCacheable(event: IAppEvent, 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 { IAppEvent } from '../../event/index.ts';\nimport { useRequestNegotiator } from './negotiator.ts';\n\nexport function getRequestAcceptableCharsets(event: IAppEvent) : string[] {\n    const negotiator = useRequestNegotiator(event);\n\n    return negotiator.charsets();\n}\n\nexport function getRequestAcceptableCharset(event: IAppEvent, 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 { IAppEvent } from '../../event/index.ts';\nimport { useRequestNegotiator } from './negotiator.ts';\n\nexport function getRequestAcceptableEncodings(event: IAppEvent) : string[] {\n    const negotiator = useRequestNegotiator(event);\n    return negotiator.encodings();\n}\n\nexport function getRequestAcceptableEncoding(event: IAppEvent, 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 { IAppEvent } from '../../event/index.ts';\nimport { useRequestNegotiator } from './negotiator.ts';\n\nexport function getRequestAcceptableLanguages(event: IAppEvent) : string[] {\n    const negotiator = useRequestNegotiator(event);\n    return negotiator.languages();\n}\n\nexport function getRequestAcceptableLanguage(event: IAppEvent, 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 { IAppEvent } from '../../event/index.ts';\nimport { getRequestHeader } from './header.ts';\n\nexport function matchRequestContentType(event: IAppEvent, 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 { DEFAULT_TRUST_PROXY, buildTrustProxyFn } from '../../utils/index.ts';\nimport type { IAppEvent } from '../../event/index.ts';\n\nexport type RequestHostNameOptions = {\n    trustProxy?: TrustProxyInput,\n};\n\nexport function getRequestHostName(event: IAppEvent, options: RequestHostNameOptions = {}) : string | undefined {\n    let trustProxy : TrustProxyFn;\n    if (typeof options.trustProxy !== 'undefined') {\n        trustProxy = buildTrustProxyFn(options.trustProxy);\n    } else {\n        trustProxy = event.appOptions.trustProxy ?? DEFAULT_TRUST_PROXY;\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 { IAppEvent } from '../../event/index.ts';\nimport type { TrustProxyFn, TrustProxyInput } from '../../utils/index.ts';\nimport { DEFAULT_TRUST_PROXY, 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: IAppEvent, options: RequestIpOptions = {}) : string | undefined {\n    let trustProxy : TrustProxyFn;\n    if (typeof options.trustProxy !== 'undefined') {\n        trustProxy = buildTrustProxyFn(options.trustProxy);\n    } else {\n        trustProxy = event.appOptions.trustProxy ?? DEFAULT_TRUST_PROXY;\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 { DEFAULT_TRUST_PROXY, buildTrustProxyFn } from '../../utils/index.ts';\nimport type { IAppEvent } from '../../event/index.ts';\n\nexport type RequestProtocolOptions = {\n    trustProxy?: TrustProxyInput,\n    default?: string,\n};\n\nexport function getRequestProtocol(\n    event: IAppEvent,\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.appOptions.trustProxy ?? DEFAULT_TRUST_PROXY;\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","import type { Key } from 'path-to-regexp';\nimport { pathToRegexp } from 'path-to-regexp';\nimport type {\n    IPathMatcher,\n    Path,\n    PathMatcherExecResult,\n    PathMatcherOptions,\n} 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 implements IPathMatcher {\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) : boolean {\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","export const PluginErrorCode = {\n    PLUGIN: 'PLUGIN',\n    NOT_INSTALLED: 'PLUGIN_NOT_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 { AppError } from '../../error/module.ts';\nimport { PluginErrorCode } from './constants.ts';\n\nexport class PluginError extends AppError {\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 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 { PathMatcher } from '../path/index.ts';\nimport type { IPathMatcher } from '../path/index.ts';\nimport type { ObjectLiteral, Route } from '../types.ts';\n\n/**\n * Build a path-to-regexp-backed `PathMatcher` for the route's mount\n * path, applying the exact-vs-prefix convention every router should\n * agree on:\n *\n * - `route.method !== undefined` → exact match (method-bound route)\n * - `route.method === undefined` → prefix match (middleware / nested\n *   app)\n *\n * Returns `undefined` when the route has no mount path — middleware\n * registered without a path matches every request.\n *\n * Routers are free to ignore this helper and build their own match\n * mechanism (radix tree, single aggregated regex, etc.) — it's\n * provided as a convenience for routers that want path-to-regexp\n * semantics with minimal boilerplate.\n */\nexport function buildRoutePathMatcher<T extends ObjectLiteral = ObjectLiteral>(\n    route: Route<T>,\n): IPathMatcher | undefined {\n    if (typeof route.path === 'undefined') {\n        return undefined;\n    }\n\n    const end = typeof route.method !== 'undefined';\n\n    // For prefix matchers a lone '/' contributes nothing useful (it\n    // matches every URL), so skip building it. Exact matchers must\n    // honor '/' — `app.get('/', …)` matches the root only.\n    if (!end && route.path === '/') {\n        return undefined;\n    }\n\n    return new PathMatcher(route.path, { end });\n}\n","import type { ICache } from '../../cache/index.ts';\nimport type { MethodNameLike } from '../../constants.ts';\nimport type { IPathMatcher } from '../../path/index.ts';\nimport type { ObjectLiteral, Route, RouteMatch } from '../../types.ts';\nimport type { BaseRouterOptions, IRouter } from '../types.ts';\nimport { buildRoutePathMatcher } from '../utils.ts';\n\n/**\n * Default router — walks registered routes linearly per request and\n * runs each route's mount-level matcher (built via `buildRoutePathMatcher`,\n * path-to-regexp-backed). Routes without a mount path (mount-less\n * middleware / nested apps registered via `.use(handler)`) match every\n * request directly — there is no per-route `matchPath()` fallback.\n *\n * Behaviour-preserving wrapper around the previous in-line stack walk\n * in `executePipelineStepLookup`. The matcher allocations live here\n * (not on the registered route), so routers using a different matching\n * strategy (radix tree, aggregated regex, …) can ignore this file\n * entirely.\n *\n * Optional per-router lookup cache: pass an `ICache` via\n * `BaseRouterOptions.cache` to skip the linear walk on repeated\n * requests for the same path. Default is no caching.\n */\nexport class LinearRouter<T extends ObjectLiteral = ObjectLiteral> implements IRouter<T> {\n    protected _routes: Route<T>[];\n\n    protected _matchers: (IPathMatcher | undefined)[];\n\n    protected cache?: ICache<readonly RouteMatch<T>[]>;\n\n    constructor(options: BaseRouterOptions<T> = {}) {\n        this._routes = [];\n        this._matchers = [];\n        this.cache = options.cache;\n    }\n\n    add(route: Route<T>): void {\n        this._routes.push(route);\n        this._matchers.push(buildRoutePathMatcher(route));\n        // A new route can change the match set for any cached path —\n        // drop the whole cache. Conservative; per-path invalidation\n        // would require knowing which paths the new route can match.\n        this.cache?.clear();\n    }\n\n    lookup(path: string, _method?: MethodNameLike): readonly RouteMatch<T>[] {\n        // LinearRouter ignores `method`: the dispatcher's own\n        // `matchHandlerMethod` check runs on every returned candidate\n        // anyway, so we simply emit every path-matching route and let\n        // the call site discriminate. Method-aware routers (TrieRouter)\n        // narrow at lookup time for the per-request perf win.\n        const cached = this.cache?.get(path);\n        if (typeof cached !== 'undefined') {\n            return cached;\n        }\n\n        const matches: RouteMatch<T>[] = [];\n\n        for (let i = 0; i < this._routes.length; i++) {\n            const route = this._routes[i]!;\n            const matcher = this._matchers[i];\n\n            if (matcher) {\n                const output = matcher.exec(path);\n                if (typeof output === 'undefined') {\n                    continue;\n                }\n                matches.push({\n                    route,\n                    index: i,\n                    params: output.params,\n                    path: output.path,\n                });\n                continue;\n            }\n\n            // No matcher → route has no mount path (middleware /\n            // mount-less router). Matches every request.\n            matches.push({\n                route,\n                index: i,\n                // Prototype-less for symmetry with TrieRouter — avoids\n                // `__proto__` / `hasOwnProperty` shadowing if user\n                // code does `'foo' in match.params`.\n                params: Object.create(null) as Record<string, string | undefined>,\n            });\n        }\n\n        this.cache?.set(path, matches);\n        return matches;\n    }\n}\n","import type { Segment } from './types.ts';\n\n/**\n * Trie-native path parser.\n *\n * Replaces the call-out to `path-to-regexp` for the syntax surface\n * the trie advertises:\n *\n *   - Static segments: `users`, `v1`\n *   - Named params:    `:id`, `:slug`\n *   - Optional params: `:id?`            (T2 — expanded to two variants)\n *   - Optional groups: `{...}`           (T2 — expanded to two variants)\n *   - Bare splat:      `*`               (matches the rest of the path)\n *   - Named splat:     `*rest`\n *\n * Returns a list of `Segment[]` *variants* — one path string can\n * expand into multiple route variants when it contains optional\n * markers. The trie inserts every variant with the same registration\n * `index` so they dedupe naturally on the candidate list.\n *\n * Returns `null` when the path uses syntax outside this surface\n * (compound segments `/files/:n.ext`, escape sequences `\\:`, regex\n * constraints, splat-not-last, …). The caller falls back to the\n * universal bucket so correctness is preserved via path-to-regexp.\n *\n * Variant cap: nested optional groups expand combinatorially. The\n * parser caps the variant count at `MAX_VARIANTS` and falls back to\n * the universal bucket above that — registration-time explosion\n * isn't worth the lookup-time win on degenerate paths.\n */\n\nconst MAX_VARIANTS = 16;\n\nconst PARAM_NAME = /^[a-zA-Z_]\\w*$/;\n\ntype ParamToken = {\n    kind: 'param';\n    name: string;\n    optional: boolean;\n};\n\ntype Token = { kind: 'literal'; value: string } |\n    ParamToken |\n    { kind: 'splat'; name: string } |\n    { kind: 'groupOpen' } |\n    { kind: 'groupClose' };\n\n/**\n * Tokenize a single path segment (the substring between two `/`).\n * Returns `null` if the segment uses syntax we don't handle.\n *\n * Each segment must yield exactly one token — compound segments\n * (`/files/:n.ext`, `/users-:id`) produce multiple tokens and so\n * trip this check, falling back to the universal bucket.\n */\nfunction tokenizeSegment(segment: string): Token | null {\n    if (segment === '') {\n        return null;\n    }\n\n    if (segment === '*') {\n        return { kind: 'splat', name: '*' };\n    }\n\n    if (segment.charAt(0) === '*') {\n        const rest = segment.slice(1);\n        if (PARAM_NAME.test(rest)) {\n            return { kind: 'splat', name: rest };\n        }\n        return null;\n    }\n\n    if (segment.charAt(0) === ':') {\n        const optional = segment.charAt(segment.length - 1) === '?';\n        const nameRaw = optional ? segment.slice(1, -1) : segment.slice(1);\n        if (PARAM_NAME.test(nameRaw)) {\n            return {\n                kind: 'param',\n                name: nameRaw,\n                optional,\n            };\n        }\n        return null;\n    }\n\n    // Plain static segment — only allow URL-safe characters. A\n    // segment with a `:` mid-string (compound) trips here too.\n    if (/^[a-zA-Z0-9_\\-.~%]+$/.test(segment)) {\n        return { kind: 'literal', value: segment };\n    }\n\n    return null;\n}\n\n/**\n * Tokenize the full path into a token stream, recognizing slash-\n * spanning optional groups (`/users{/edit/:id}`).\n *\n * The group-open marker is emitted in place of the leading `/`\n * inside `{...}`; group-close before the trailing `}`. The walker\n * later expands by either keeping the run between markers or\n * dropping it.\n */\nfunction tokenizePath(path: string): Token[] | null {\n    const trimmed = path.charAt(0) === '/' ? path.slice(1) : path;\n    if (trimmed === '') {\n        return [];\n    }\n\n    const tokens: Token[] = [];\n    let i = 0;\n    const n = trimmed.length;\n\n    while (i < n) {\n        if (trimmed.charAt(i) === '{') {\n            // Find matching `}` (no nesting support — fall back if\n            // we see a nested `{` before the close).\n            let close = -1;\n            for (let j = i + 1; j < n; j++) {\n                const c = trimmed.charAt(j);\n                if (c === '{') {\n                    return null;\n                }\n                if (c === '}') {\n                    close = j;\n                    break;\n                }\n            }\n            if (close === -1) {\n                return null;\n            }\n            const inner = trimmed.slice(i + 1, close);\n            // Inner must start with `/` so the group is slash-spanning\n            // (matches path-to-regexp v8's `{/segment}` shape).\n            if (inner.charAt(0) !== '/') {\n                return null;\n            }\n            // What follows the closing `}` must end the segment —\n            // either end-of-path, a `/` separator, or another `{`\n            // group. Anything else (e.g. `/a{/b}c`) is compound\n            // syntax the trie can't represent; fall back to the\n            // universal bucket so path-to-regexp can handle it.\n            const after = close + 1 < n ? trimmed.charAt(close + 1) : '';\n            if (after !== '' && after !== '/' && after !== '{') {\n                return null;\n            }\n            tokens.push({ kind: 'groupOpen' });\n            const innerTokens = tokenizePath(inner);\n            if (innerTokens === null) {\n                return null;\n            }\n            for (const t of innerTokens) {\n                tokens.push(t);\n            }\n            tokens.push({ kind: 'groupClose' });\n            i = close + 1;\n            continue;\n        }\n\n        // Read until next `/` or `{`.\n        let segEnd = i;\n        while (segEnd < n) {\n            const c = trimmed.charAt(segEnd);\n            if (c === '/' || c === '{') {\n                break;\n            }\n            segEnd++;\n        }\n        const segment = trimmed.slice(i, segEnd);\n        if (segment !== '') {\n            const token = tokenizeSegment(segment);\n            if (token === null) {\n                return null;\n            }\n            tokens.push(token);\n        }\n        i = segEnd;\n        if (i < n && trimmed.charAt(i) === '/') {\n            i++; // skip the separator\n        }\n    }\n\n    return tokens;\n}\n\n/**\n * Expand the token stream into one or more concrete `Token[]`\n * variants by:\n *   1. Splitting `groupOpen` … `groupClose` runs into a \"with run\"\n *      and a \"without run\" choice (one optional group → ×2 variants).\n *   2. Splitting `param.optional = true` into a \"with\" and \"without\"\n *      choice (one `:id?` → ×2 variants).\n *\n * Caps at `MAX_VARIANTS` — beyond that, returns `null` so the path\n * falls back to the universal bucket.\n *\n * Returns `Token[][]` (not `Segment[][]`) so the recursive\n * group-expansion can splice inner variants back into the outer\n * token stream without a lossy round-trip through `Segment`.\n * `parsePath` does the final `Token → Segment` projection.\n */\nfunction expand(tokens: Token[]): Token[][] | null {\n    let variants: Token[][] = [[]];\n\n    for (let i = 0; i < tokens.length; i++) {\n        const token = tokens[i]!;\n\n        if (token.kind === 'groupOpen') {\n            // Find matching `groupClose`. Nested groups already\n            // rejected at tokenize time so this is one level deep.\n            let depth = 1;\n            let close = -1;\n            for (let j = i + 1; j < tokens.length; j++) {\n                const t = tokens[j]!;\n                if (t.kind === 'groupOpen') depth++;\n                else if (t.kind === 'groupClose') {\n                    depth--;\n                    if (depth === 0) {\n                        close = j;\n                        break;\n                    }\n                }\n            }\n            if (close === -1) {\n                return null;\n            }\n            const inner = tokens.slice(i + 1, close);\n            const expandedInner = expand(inner);\n            if (expandedInner === null) {\n                return null;\n            }\n            // Two choices for this run: keep without, or splice in\n            // each inner variant. Cap-check before each push so\n            // we never exceed `MAX_VARIANTS`.\n            const next: Token[][] = [];\n            for (const v of variants) {\n                if (next.length >= MAX_VARIANTS) {\n                    return null;\n                }\n                next.push(v.slice());\n                for (const innerVariant of expandedInner) {\n                    if (next.length >= MAX_VARIANTS) {\n                        return null;\n                    }\n                    next.push(v.concat(innerVariant));\n                }\n            }\n            variants = next;\n            i = close;\n            continue;\n        }\n\n        if (token.kind === 'param' && token.optional) {\n            const stripped: Token = {\n                kind: 'param',\n                name: token.name,\n                optional: false,\n            };\n            const next: Token[][] = [];\n            for (const v of variants) {\n                if (next.length >= MAX_VARIANTS) {\n                    return null;\n                }\n                next.push(v.slice());\n                if (next.length >= MAX_VARIANTS) {\n                    return null;\n                }\n                next.push(v.concat([stripped]));\n            }\n            variants = next;\n            continue;\n        }\n\n        for (const v of variants) {\n            v.push(token);\n        }\n    }\n\n    return variants;\n}\n\nfunction tokenToSegment(t: Token): Segment | null {\n    if (t.kind === 'literal') return { kind: 'static', value: t.value };\n    if (t.kind === 'param') return { kind: 'param', name: t.name };\n    if (t.kind === 'splat') return { kind: 'splat', name: t.name };\n    // groupOpen/groupClose should be consumed by `expand`; if any\n    // leak through, the path is malformed.\n    return null;\n}\n\n/**\n * Stable, structural identity for a variant — used to drop duplicate\n * expansions like `/users{/:id?}` (which produces the bare-`/users`\n * variant twice: once from the \"without group\" branch and once from\n * the \"with group, without optional param\" branch).\n */\nfunction variantKey(segs: Segment[]): string {\n    let out = '';\n    for (const s of segs) {\n        if (s.kind === 'static') out += `/s:${s.value}`;\n        else if (s.kind === 'param') out += `/p:${s.name}`;\n        else out += `/*:${s.name}`;\n    }\n    return out;\n}\n\nexport function parsePath(path: string): Segment[][] | null {\n    const tokens = tokenizePath(path);\n    if (tokens === null) {\n        return null;\n    }\n    const variants = expand(tokens);\n    if (variants === null) {\n        return null;\n    }\n\n    const result: Segment[][] = [];\n    const seen = new Set<string>();\n\n    for (const v of variants) {\n        const segs: Segment[] = [];\n        for (const t of v) {\n            const s = tokenToSegment(t);\n            if (s === null) {\n                return null;\n            }\n            segs.push(s);\n        }\n\n        // Splat must be the terminal segment in any variant —\n        // otherwise the trie's `insertIntoTrie` would silently drop\n        // every segment after the splat (T3 dropped the\n        // `matcher.exec` confirm pass that previously caught this).\n        // Fall back to the universal bucket so path-to-regexp can\n        // handle the route honestly.\n        for (let i = 0; i < segs.length - 1; i++) {\n            if (segs[i]!.kind === 'splat') {\n                return null;\n            }\n        }\n\n        const key = variantKey(segs);\n        if (seen.has(key)) {\n            continue;\n        }\n        seen.add(key);\n        result.push(segs);\n    }\n    return result;\n}\n","import type { ObjectLiteral } from '../../types.ts';\nimport type { MethodBuckets, TrieNode } from './types.ts';\n\nexport function createMethodBuckets<T extends ObjectLiteral = ObjectLiteral>(): MethodBuckets<T> {\n    return Object.create(null) as MethodBuckets<T>;\n}\n\nexport function createTrieNode<T extends ObjectLiteral = ObjectLiteral>(): TrieNode<T> {\n    return {\n        staticChildren: new Map(),\n        splatRoutes: createMethodBuckets<T>(),\n        exactRoutes: createMethodBuckets<T>(),\n        prefixRoutes: [],\n    };\n}\n","import { MethodName } from '../../constants.ts';\nimport type { MethodNameLike } from '../../constants.ts';\nimport type { ICache } from '../../cache/index.ts';\nimport type { ObjectLiteral, Route, RouteMatch } from '../../types.ts';\nimport type { BaseRouterOptions, IRouter } from '../types.ts';\nimport { buildRoutePathMatcher } from '../utils.ts';\nimport type {\n    IndexedRoute,\n    MethodBuckets,\n    ParamCapture,\n    Segment,\n    TrieNode,\n} from './types.ts';\nimport { parsePath } from './parser.ts';\n\nimport { createTrieNode } from './node.ts';\n\nfunction decodeOrRaw(s: string): string {\n    try {\n        return decodeURIComponent(s);\n    } catch {\n        return s;\n    }\n}\n\n/**\n * Build a `params` object from a request's pre-split segments using\n * the variant's pre-computed `ParamCapture[]`. No regex execution —\n * each capture is one indexed read from `segments` (and a join for\n * splats). Replaces the `matcher.exec` confirm pass for trie-walked\n * routes (T3).\n */\nfunction extractTrieParams(\n    segments: string[],\n    indexMap: ParamCapture[],\n): Record<string, string | undefined> {\n    const out = Object.create(null) as Record<string, string | undefined>;\n    for (const cap of indexMap) {\n        if (cap.kind === 'segment') {\n            out[cap.name] = decodeOrRaw(segments[cap.depth]!);\n        } else {\n            // Splat: capture every remaining segment, joined with '/'.\n            const slice = segments.slice(cap.depth).join('/');\n            out[cap.name] = decodeOrRaw(slice);\n        }\n    }\n    return out;\n}\n\n/**\n * Compute `match.path` (the matched-prefix string) from the request's\n * segments and the variant's recorded depth.\n *\n * - Non-splat variants: prefix = `segments[0..matchDepth].join('/')` —\n *   exactly what the variant consumed (request length = variant\n *   length for exact, request length ≥ variant length for prefix).\n * - Splat variants: the splat absorbed every remaining segment, so\n *   the matched prefix is the entire request path. This mirrors what\n *   `path-to-regexp`'s `output.path` would have returned pre-Phase-2\n *   for `/files/*rest` matching `/files/a/b` (`/files/a/b`, not\n *   `/files`).\n */\nfunction trieMatchedPath(\n    segments: string[],\n    matchDepth: number,\n    splatTerminated: boolean,\n): string {\n    const upTo = splatTerminated ? segments.length : matchDepth;\n    if (upTo === 0) {\n        return '/';\n    }\n    return `/${segments.slice(0, upTo).join('/')}`;\n}\n\n/**\n * Pre-compute the `ParamCapture[]` for a variant's segments. Walk\n * the segments in order; emit one entry per `param` segment and a\n * terminal one for `splat` (always last). Static segments are\n * structurally consumed by the trie walk; they don't appear here.\n */\nfunction buildParamsIndexMap(segments: Segment[]): ParamCapture[] {\n    const out: ParamCapture[] = [];\n    for (const [i, seg] of segments.entries()) {\n        if (seg.kind === 'param') {\n            out.push({\n                kind: 'segment',\n                depth: i,\n                name: seg.name,\n            });\n        } else if (seg.kind === 'splat') {\n            out.push({\n                kind: 'splat',\n                depth: i,\n                name: seg.name,\n            });\n            // Splats are always last in a variant — the trie parser\n            // emits at most one per variant.\n            break;\n        }\n    }\n    return out;\n}\n\n/**\n * Decide which method buckets a given request method should pull\n * from. Always includes `''` (method-agnostic). For HEAD also\n * includes GET (per `matchHandlerMethod`). For OPTIONS or no-method\n * lookups, returns `null` to signal \"emit every bucket\" — needed so\n * `event.methodsAllowed` is populated for OPTIONS auto-Allow and so\n * `IRouter.lookup(path)` (no method) keeps returning a complete\n * candidate set.\n */\nfunction methodBucketKeys(method: MethodNameLike | undefined): readonly string[] | null {\n    if (typeof method === 'undefined' || method === MethodName.OPTIONS) {\n        return null;\n    }\n    if (method === MethodName.HEAD) {\n        return ['', MethodName.HEAD, MethodName.GET];\n    }\n    return ['', method];\n}\n\nfunction emitBucket<T extends ObjectLiteral>(\n    buckets: MethodBuckets<T>,\n    method: MethodNameLike | undefined,\n    out: IndexedRoute<T>[],\n): void {\n    const keys = methodBucketKeys(method);\n    if (keys === null) {\n        for (const k in buckets) {\n            const list = buckets[k]!;\n            for (const r of list) out.push(r);\n        }\n        return;\n    }\n    for (const k of keys) {\n        const list = buckets[k];\n        if (!list) continue;\n        for (const r of list) out.push(r);\n    }\n}\n\nfunction hasAnyBucket<T extends ObjectLiteral>(buckets: MethodBuckets<T>): boolean {\n    // eslint-disable-next-line no-unreachable-loop\n    for (const _k in buckets) {\n        return true;\n    }\n    return false;\n}\n\nfunction pushIntoBucket<T extends ObjectLiteral>(\n    buckets: MethodBuckets<T>,\n    methodKey: string,\n    route: IndexedRoute<T>,\n): void {\n    const bucket = buckets[methodKey];\n    if (bucket) {\n        bucket.push(route);\n    } else {\n        buckets[methodKey] = [route];\n    }\n}\n\n/**\n * Radix-trie router — registers routes into a per-segment tree at\n * `add()` time and walks the tree at `lookup()` to collect\n * candidates by structure rather than by linear scan.\n *\n * Inspired by Hono's `TrieRouter` and rou3. The trie handles\n * routup's path vocabulary directly via its own parser\n * (`./parser.ts`):\n *\n *   - Static segments (`/users`)\n *   - Named params (`:id`)\n *   - Optional params (`:id?`) — expanded to two route variants at\n *     registration (T2)\n *   - Optional groups (`/users{/edit}`) — same expansion strategy\n *   - Bare and named splats (`/files/*`, `/files/*rest`)\n *\n * Per-leaf storage is bucketed by HTTP method (T4) so lookup\n * narrows to the request method's bucket(s) instead of emitting\n * every entry at the leaf and letting the dispatcher's filter\n * discard mismatches.\n *\n * Param extraction is `paramsIndexMap`-driven (T3): a pre-built\n * `Array<{ depth, name }>` per variant lets `extractTrieParams`\n * read params straight from the request's pre-split segments — no\n * regex execution per match.\n *\n * Paths the trie parser doesn't handle (compound segments like\n * `/files/:n.ext`, escape sequences `\\:`, regex constraints) and\n * empty/root paths fall through to the `universal` bucket. That\n * bucket still uses `path-to-regexp` via `buildRoutePathMatcher`,\n * so correctness is preserved.\n *\n * Pure-static-spine fast path (`shortCircuit`): when the request\n * walks a static spine with no param/splat/prefix siblings on any\n * traversed node, the leaf's `exactRoutes` (filtered to the request\n * method's buckets) is the full answer — no need to walk the param\n * branch or collect prefix candidates at intermediate nodes.\n */\nexport class TrieRouter<T extends ObjectLiteral = ObjectLiteral> implements IRouter<T> {\n    /**\n     * Monotonic counter assigned as the registration `index` on each\n     * route — the dispatch loop uses it to preserve registration\n     * order across the candidate list. App owns the canonical\n     * `Route<T>[]` list (Plan 019); the trie no longer keeps a\n     * parallel copy.\n     */\n    protected _routeCount: number;\n\n    protected root: TrieNode<T>;\n\n    /**\n     * Routes that bypass the trie — registered with no path, with\n     * the root path `/`, or with a path containing syntax the\n     * parser doesn't recognise. Walked linearly on every lookup,\n     * merged into the result in registration order.\n     */\n    protected universal: IndexedRoute<T>[];\n\n    protected cache?: ICache<readonly RouteMatch<T>[]>;\n\n    constructor(options: BaseRouterOptions<T> = {}) {\n        this._routeCount = 0;\n        this.root = createTrieNode<T>();\n        this.universal = [];\n        this.cache = options.cache;\n    }\n\n    add(route: Route<T>): void {\n        const index = this._routeCount++;\n\n        // Empty/root paths bypass the trie. We still build a matcher\n        // — `buildRoutePathMatcher` returns one only for the cases\n        // that actually need confirmation:\n        //   - `app.get('/', h)` (exact match) → matcher rejects\n        //     non-`/` requests so the route doesn't promiscuously\n        //     match every path.\n        //   - `app.use('/', mw)` / `app.use(mw)` (prefix or no path)\n        //     → returns `undefined`; the lookup loop treats the\n        //     route as \"matches every request\" via the no-matcher\n        //     branch, which is exactly what middleware wants.\n        if (typeof route.path !== 'string' || route.path === '' || route.path === '/') {\n            this.universal.push({\n                route,\n                index,\n                matcher: buildRoutePathMatcher(route),\n            });\n            this.cache?.clear();\n            return;\n        }\n\n        const variants = parsePath(route.path);\n        if (variants === null) {\n            // Trie parser doesn't handle this syntax (compound\n            // segments like `/files/:n.ext`, escape sequences,\n            // splat-not-last, …). Fall back to path-to-regexp.\n            this.universal.push({\n                route,\n                index,\n                matcher: buildRoutePathMatcher(route),\n            });\n            this.cache?.clear();\n            return;\n        }\n\n        // Each variant becomes an `IndexedRoute` sharing the same\n        // registration `index` so the candidate dedupe keeps them\n        // collapsed to one match per request.\n        for (const segments of variants) {\n            this.insertIntoTrie(segments, route, index);\n        }\n        this.cache?.clear();\n    }\n\n    lookup(path: string, method?: MethodNameLike): readonly RouteMatch<T>[] {\n        // Cache key includes the method bucket — different methods at\n        // the same path now resolve to different candidate sets, so\n        // sharing a cache entry across methods would leak matches.\n        const cacheKey = `${method ?? ''}\\t${path}`;\n        const cached = this.cache?.get(cacheKey);\n        if (typeof cached !== 'undefined') {\n            return cached;\n        }\n\n        const candidates: IndexedRoute<T>[] = [];\n\n        for (const u of this.universal) {\n            candidates.push(u);\n        }\n\n        const segments = this.parseRequestPath(path);\n        const shortCircuit = this.shortCircuit(segments, method);\n        if (shortCircuit !== null) {\n            for (const c of shortCircuit) {\n                candidates.push(c);\n            }\n        } else {\n            this.walk(this.root, segments, 0, candidates, method);\n        }\n\n        // Sort primarily by registration `index` (preserves dispatch\n        // order across the candidate list). When multiple variants\n        // of one route match the same request — e.g. a prefix\n        // `use('/api/:version?', child)` whose `/api` and\n        // `/api/:version` variants both fire for `/api/v1/...` —\n        // we pick the *most specific* one (greatest `matchDepth`),\n        // so the more-derived variant's `params` and `match.path`\n        // win over the bare-prefix variant. Universal-bucket\n        // candidates have no `matchDepth`; treat as -1 so a trie\n        // variant of the same route wins (in practice they don't\n        // overlap — a route is in either bucket).\n        candidates.sort((a, b) => {\n            if (a.index !== b.index) return a.index - b.index;\n            const ad = a.matchDepth ?? -1;\n            const bd = b.matchDepth ?? -1;\n            return bd - ad;\n        });\n\n        const matches: RouteMatch<T>[] = [];\n        let lastIndex = -1; // dedupe — multiple variants of one route share `index`\n        for (const candidate of candidates) {\n            const {\n                route,\n                index,\n                matcher,\n                paramsIndexMap,\n                matchDepth,\n            } = candidate;\n\n            if (index === lastIndex) {\n                continue;\n            }\n\n            if (matcher) {\n                // Universal-bucket route: still uses path-to-regexp.\n                const output = matcher.exec(path);\n                if (typeof output === 'undefined') {\n                    continue;\n                }\n                matches.push({\n                    route,\n                    index,\n                    params: this.assignParams(output.params),\n                    path: output.path,\n                });\n                lastIndex = index;\n                continue;\n            }\n\n            if (paramsIndexMap && typeof matchDepth === 'number') {\n                // Trie-walked route: extract params from the request\n                // segments using the pre-built index map. No regex.\n                matches.push({\n                    route,\n                    index,\n                    params: extractTrieParams(segments, paramsIndexMap),\n                    path: trieMatchedPath(segments, matchDepth, candidate.splatTerminated === true),\n                });\n                lastIndex = index;\n                continue;\n            }\n\n            // Universal-bucket route with no matcher (empty / root path).\n            matches.push({\n                route,\n                index,\n                params: Object.create(null) as Record<string, string | undefined>,\n            });\n            lastIndex = index;\n        }\n\n        this.cache?.set(cacheKey, matches);\n        return matches;\n    }\n\n    /**\n     * T1: returns the pre-computed candidate list when the request's\n     * static spine has no param sibling, no prefix routes, and no\n     * splats along the way. The leaf node's `exactRoutes` (filtered\n     * to the request method's buckets) is then the complete answer —\n     * no need to walk the param branch or collect prefix/splat\n     * candidates from intermediate nodes. When any branch is\n     * encountered, returns `null` and the caller falls through to\n     * the regular `walk`.\n     */\n    protected shortCircuit(segments: string[], method: MethodNameLike | undefined): IndexedRoute<T>[] | null {\n        let node = this.root;\n\n        for (const segment of segments) {\n            // Any branch at this node disqualifies the fast path: a\n            // param-child might match the current segment, a splat\n            // would fire, and prefix routes would belong in the\n            // result. All of these need the full walk.\n            if (node.paramChild || hasAnyBucket(node.splatRoutes) || node.prefixRoutes.length > 0) {\n                return null;\n            }\n\n            const child = node.staticChildren.get(segment!);\n            if (!child) {\n                return null;\n            }\n            node = child;\n        }\n\n        if (node.paramChild || hasAnyBucket(node.splatRoutes) || node.prefixRoutes.length > 0) {\n            return null;\n        }\n\n        // Pure static spine reached the leaf — `exactRoutes` (for the\n        // request method's relevant buckets) is the complete answer.\n        const out: IndexedRoute<T>[] = [];\n        emitBucket(node.exactRoutes, method, out);\n        return out;\n    }\n\n    protected parseRequestPath(path: string): string[] {\n        const trimmed = path.charAt(0) === '/' ? path.slice(1) : path;\n        if (trimmed === '') {\n            return [];\n        }\n        const parts = trimmed.split('/');\n        const result: string[] = [];\n        for (const part of parts) {\n            if (part !== '') {\n                result.push(part);\n            }\n        }\n        return result;\n    }\n\n    protected insertIntoTrie(segments: Segment[], route: Route<T>, index: number): void {\n        let node = this.root;\n        const exact = this.isExactMatchRoute(route);\n        const methodKey = route.method ?? '';\n        const paramsIndexMap = buildParamsIndexMap(segments);\n\n        for (const [i, segment] of segments.entries()) {\n            const seg = segment!;\n\n            if (seg.kind === 'splat') {\n                // Splat consumes the rest of the request path. The\n                // splat segment itself doesn't create a trie child\n                // node — it lives on the *current* node. So\n                // `matchDepth` is the number of segments matched\n                // before the splat (== current trie depth == `i`,\n                // the splat's index in the variant).\n                pushIntoBucket(node.splatRoutes, methodKey, {\n                    route,\n                    index,\n                    paramsIndexMap,\n                    matchDepth: i,\n                    splatTerminated: true,\n                });\n                return;\n            }\n\n            if (seg.kind === 'param') {\n                if (!node.paramChild) {\n                    node.paramChild = createTrieNode();\n                }\n                node = node.paramChild;\n                continue;\n            }\n\n            let child = node.staticChildren.get(seg.value);\n            if (!child) {\n                child = createTrieNode();\n                node.staticChildren.set(seg.value, child);\n            }\n            node = child;\n        }\n\n        const indexed: IndexedRoute<T> = {\n            route,\n            index,\n            paramsIndexMap,\n            matchDepth: segments.length,\n        };\n\n        if (exact) {\n            pushIntoBucket(node.exactRoutes, methodKey, indexed);\n        } else {\n            // Prefix routes (middleware / mounted apps) stay flat —\n            // they're method-agnostic by design.\n            node.prefixRoutes.push(indexed);\n        }\n    }\n\n    protected walk(\n        node: TrieNode<T>,\n        segments: string[],\n        depth: number,\n        collected: IndexedRoute<T>[],\n        method: MethodNameLike | undefined,\n    ): void {\n        // Splats at this depth match any request path that reaches here.\n        emitBucket(node.splatRoutes, method, collected);\n\n        if (depth === segments.length) {\n            // Request path is fully consumed at this node: collect\n            // both exact-match and prefix-match routes that ended here.\n            emitBucket(node.exactRoutes, method, collected);\n            for (const p of node.prefixRoutes) {\n                collected.push(p);\n            }\n            return;\n        }\n\n        // Going deeper — prefix routes at this node match any\n        // continuation (middleware / nested apps).\n        for (const p of node.prefixRoutes) {\n            collected.push(p);\n        }\n\n        const seg = segments[depth]!;\n\n        const staticChild = node.staticChildren.get(seg);\n        if (staticChild) {\n            this.walk(staticChild, segments, depth + 1, collected, method);\n        }\n\n        if (node.paramChild) {\n            this.walk(node.paramChild, segments, depth + 1, collected, method);\n        }\n    }\n\n    protected isExactMatchRoute(route: Route<T>): boolean {\n        return typeof route.method !== 'undefined';\n    }\n\n    /**\n     * T5: copy params onto a prototype-less object so downstream\n     * lookups skip prototype-chain traversal and avoid `__proto__` /\n     * `hasOwnProperty` shadowing from user-controlled segment values.\n     */\n    protected assignParams(\n        source: Record<string, string | undefined>,\n    ): Record<string, string | undefined> {\n        const out = Object.create(null) as Record<string, string | undefined>;\n        for (const k in source) {\n            if (Object.prototype.hasOwnProperty.call(source, k)) {\n                out[k] = source[k];\n            }\n        }\n        return out;\n    }\n}\n","import type { ICache } from '../../cache/index.ts';\nimport type { ObjectLiteral, Route, RouteMatch } from '../../types.ts';\nimport { LinearRouter } from '../linear/index.ts';\nimport { TrieRouter } from '../trie/index.ts';\nimport type { BaseRouterOptions, IRouter } from '../types.ts';\n\n/**\n * Default crossover. Empirically `LinearRouter` wins for small route\n * counts (no per-request trie walk overhead, no static-spine setup);\n * `TrieRouter` wins past ~30 entries on typical workloads. Override\n * via `SmartRouterOptions.threshold` when a benchmark says otherwise\n * for your route shape.\n */\nconst DEFAULT_THRESHOLD = 30;\n\nexport type SmartRouterOptions<T extends ObjectLiteral = ObjectLiteral> = BaseRouterOptions<T> & {\n    /**\n         * Route count at or above which `SmartRouter` switches from\n         * `LinearRouter` (faster at small N) to `TrieRouter` (faster\n         * at large N). Default `30`.\n         */\n    threshold?: number;\n};\n\n/**\n * Auto-selecting router. Accumulates registered routes in a pending\n * buffer; on the first `lookup()` call, picks `LinearRouter` or\n * `TrieRouter` based on the registered route count and replays the\n * pending list onto the chosen inner router. Every subsequent call\n * — `add`, `lookup` — forwards to the inner.\n *\n * Use this when you don't want to commit to a router family up-front\n * (e.g. a library that registers a variable number of routes\n * depending on configuration). For known workloads, prefer the\n * concrete router — `SmartRouter` adds one indirection per call.\n *\n * Inspired by Hono's `SmartRouter` (which auto-selects across more\n * candidates including `RegExpRouter`); ours covers the only choice\n * that matters in routup today: linear-vs-trie at the registration-\n * size crossover.\n */\nexport class SmartRouter<T extends ObjectLiteral = ObjectLiteral> implements IRouter<T> {\n    protected inner?: IRouter<T>;\n\n    protected pending: Route<T>[] = [];\n\n    protected readonly threshold: number;\n\n    /**\n     * Cache handed off to whichever inner router gets chosen. Stays\n     * `undefined` if the user didn't configure one.\n     */\n    protected readonly cache?: ICache<readonly RouteMatch<T>[]>;\n\n    constructor(options: SmartRouterOptions<T> = {}) {\n        this.threshold = options.threshold ?? DEFAULT_THRESHOLD;\n        this.cache = options.cache;\n    }\n\n    add(route: Route<T>): void {\n        if (this.inner) {\n            this.inner.add(route);\n            return;\n        }\n        this.pending.push(route);\n    }\n\n    lookup(path: string, method?: string): readonly RouteMatch<T>[] {\n        if (!this.inner) {\n            this.inner = this.choose();\n            for (const r of this.pending) {\n                this.inner.add(r);\n            }\n            this.pending = [];\n        }\n        return this.inner.lookup(path, method);\n    }\n\n    /**\n     * Pick the inner router based on the registered route count.\n     * `LinearRouter` for tiny tables, `TrieRouter` past the\n     * configured threshold.\n     *\n     * @protected\n     */\n    protected choose(): IRouter<T> {\n        if (this.pending.length < this.threshold) {\n            return new LinearRouter<T>({ cache: this.cache });\n        }\n        return new TrieRouter<T>({ cache: this.cache });\n    }\n}\n","import {\n    type EtagFn,\n    type TrustProxyFn,\n    buildEtagFn,\n    buildTrustProxyFn,\n} from '../utils/index.ts';\nimport type { AppOptions, AppOptionsInput } from './types.ts';\n\nexport function normalizeAppOptions(input: AppOptionsInput): AppOptions {\n    let etag : EtagFn | null | undefined;\n    if (typeof input.etag !== 'undefined') {\n        // Keep `false` (and `null` from already-normalized options\n        // being re-spread) as the literal `null` sentinel so\n        // toResponse() can synchronously skip the ETag path. A truthy\n        // no-op fn (the previous behavior) forced an `await\n        // applyEtag(...)` microtask hop on every request.\n        if (input.etag === null || input.etag === false) {\n            etag = null;\n        } else {\n            etag = buildEtagFn(input.etag);\n        }\n    }\n\n    let trustProxy : TrustProxyFn | undefined;\n    if (typeof input.trustProxy !== 'undefined') {\n        trustProxy = buildTrustProxyFn(input.trustProxy);\n    }\n\n    if (typeof input.timeout !== 'undefined') {\n        if (\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            !Number.isFinite(input.handlerTimeout) ||\n            input.handlerTimeout <= 0\n        ) {\n            delete input.handlerTimeout;\n        }\n    }\n\n    return {\n        ...input,\n        etag,\n        trustProxy,\n    };\n}\n","export const AppSymbol = Symbol.for('App');\n","import { hasInstanceof } from '@ebec/core';\nimport { isObject } from '../utils/index.ts';\nimport { AppSymbol } from './constants.ts';\nimport type { IApp } from './types.ts';\n\n/**\n * Discriminate an `IApp` argument from handlers, plugins, and other\n * inputs `App.use()` accepts. Two-stage check:\n *\n *   1. Fast path: brand check (`hasInstanceof` against `AppSymbol`).\n *      Hits for every instance of the bundled `App` class and any\n *      subclass that calls `markInstanceof(this, AppSymbol)` — that's\n *      the common case, so we want it to be a single property lookup\n *      with no key-by-key probing.\n *\n *   2. Fallback: structural check for the `IApp` surface `flatten()`\n *      reads at mount time (`fetch`, `routes`, `plugins`,\n *      `pluginSingletons`). Lets any object implementing the `IApp`\n *      contract — not just instances of the bundled `App` class — be\n *      mounted via `app.use(child)`.\n */\nexport function isAppInstance(input: unknown): input is IApp {\n    if (hasInstanceof(input, AppSymbol)) {\n        return true;\n    }\n    if (!isObject(input)) {\n        return false;\n    }\n    return typeof input.fetch === 'function' &&\n        Array.isArray(input.routes) &&\n        isObject(input.plugins) &&\n        isObject(input.pluginSingletons);\n}\n","import { markInstanceof } from '@ebec/core';\nimport { HeaderName, MethodName } from '../constants.ts';\nimport { DispatcherEvent } from '../dispatcher/index.ts';\nimport type { IDispatcherEvent } from '../dispatcher/index.ts';\nimport type { AppRequest } from '../event/index.ts';\nimport { createError } from '../error/index.ts';\nimport {\n    Handler,\n    type HandlerOptions,\n    HandlerType,\n    isHandler,\n    isHandlerOptions,\n    matchHandlerMethod,\n} from '../handler/index.ts';\nimport type { Path } from '../path/index.ts';\nimport { isPath } from '../path/index.ts';\nimport type { Plugin, PluginInstallContext } from '../plugin/index.ts';\nimport { isPlugin } from '../plugin/index.ts';\nimport { normalizeAppOptions } from './options.ts';\nimport {\n    acceptsJson,\n    joinPaths,\n    withLeadingSlash,\n} from '../utils/index.ts';\nimport { AppSymbol } from './constants.ts';\nimport { LinearRouter } from '../router/linear/index.ts';\nimport type { IRouter } from '../router/types.ts';\nimport type {\n    AppContext,\n    AppOptions,\n    IApp,\n} from './types.ts';\nimport { isAppInstance } from './check.ts';\nimport type { Route, RouteMatch } from '../types.ts';\n\n/**\n * Merge resolver-supplied path params into `event.params` *only* when\n * `match.params` actually has keys. Skipping the object spread on the\n * empty-params path (every static route, every middleware match) saves\n * an allocation per match — the hottest path in static-route apps.\n */\nfunction mergeMatchParams(\n    event: IDispatcherEvent,\n    matchParams: Record<string, string | undefined>,\n): void {\n    // Cheap emptiness probe — short-circuits on the first own key.\n    let hasKeys = false;\n    // eslint-disable-next-line no-unreachable-loop\n    for (const _k in matchParams) {\n        hasKeys = true;\n        break;\n    }\n    if (!hasKeys) {\n        return;\n    }\n    event.params = {\n        ...event.params,\n        ...matchParams,\n    };\n}\n\nexport class App implements IApp {\n    /**\n     * A label for the App instance.\n     */\n    readonly name?: string;\n\n    /**\n     * Registration-time path prefix for entries registered on this\n     * App. Local to this instance — never inherited from a parent.\n     *\n     * @protected\n     */\n    protected _path?: Path;\n\n    /**\n     * Pluggable router (route table) — owns the \"which entries match\n     * this path?\" lookup. Defaults to `LinearRouter` (walks entries\n     * linearly per request); swap in via `AppContext.router`\n     * for a radix/trie implementation on apps with many routes.\n     *\n     * @protected\n     */\n    protected router: IRouter<Handler>;\n\n    /**\n     * Normalized options for this App instance.\n     *\n     * Frozen on construction — once published to `event.appOptions`\n     * it is shared across all requests, and a handler must not be\n     * able to mutate router-global state.\n     */\n    protected _options: Readonly<AppOptions>;\n\n    /**\n     * Registry of installed plugins on this App, keyed by plugin name\n     * then by canonical mount key (the joined `this._path` +\n     * install-time `path`, falling back to `'/'` for a root install).\n     * Inner-map value is the plugin version (or `undefined`).\n     *\n     * Per-path keying lets `hasPluginAt` answer \"is plugin X mounted at\n     * /api?\" precisely. By default `install()` is permissive and\n     * appends — same `(name, key)` writes the latest version. Plugins\n     * opt into deduplication via `singleton` (any-path) or\n     * `singletonByPath` (same-path) flags.\n     *\n     * Read by `flatten()` when merging a child's registry into this\n     * one, so `parent.hasPlugin('foo')` reflects plugins installed on\n     * mounted children too.\n     *\n     * @protected\n     */\n    protected _plugins: Map<string, Map<string, string | undefined>>;\n\n    /**\n     * Names of plugins installed with `singleton: true`. Re-installing\n     * any of these names — even at a different mount path — is a\n     * silent no-op. The claim is sticky: once a name is in here, it\n     * stays for the lifetime of the App. Propagated through\n     * `flatten()` so a child's singleton claim survives the mount.\n     *\n     * @protected\n     */\n    protected _pluginSingletons: Set<string>;\n\n    /**\n     * Every route registered on this App, in registration order.\n     *\n     * Read by `use(otherApp)` to snapshot routes at flatten time.\n     * Late mutations to `_routes` after a flatten do not propagate.\n     */\n    protected _routes: Route<Handler>[] = [];\n\n    // --------------------------------------------------\n\n    constructor(input: AppContext = {}) {\n        this.name = input.name;\n        this._path = input.path;\n\n        this._plugins = new Map();\n        this._pluginSingletons = new Set();\n        this.router = input.router ?? new LinearRouter<Handler>();\n\n        this._options = Object.freeze(normalizeAppOptions(input.options ?? {}));\n\n        // Brand the instance so `isAppInstance` can fast-path on\n        // class-instance arguments before falling back to the\n        // structural shape check.\n        markInstanceof(this, AppSymbol);\n    }\n\n    // --------------------------------------------------\n\n    /**\n     * Public read of the canonical route list. Used by `use(child)`\n     * to snapshot the child's routes at flatten time. Returned\n     * as `readonly` — callers must not mutate.\n     */\n    get routes(): readonly Route<Handler>[] {\n        return this._routes;\n    }\n\n    /**\n     * Public read of the installed-plugin registry. Used by `flatten()`\n     * to merge a child's plugins into this App without reaching into\n     * the child's protected fields.\n     *\n     * Outer key: plugin name. Inner key: canonical mount path (`'/'`\n     * for root mounts). Inner value: installed version (or `undefined`).\n     *\n     * Returned as nested `ReadonlyMap` — callers must not mutate; go\n     * through `app.use(plugin)` to install.\n     */\n    get plugins(): ReadonlyMap<string, ReadonlyMap<string, string | undefined>> {\n        return this._plugins;\n    }\n\n    /**\n     * Public read of the sticky singleton-claim set. Once a plugin\n     * name is claimed singleton on an App, every subsequent install\n     * of that name is a silent no-op. Used by `flatten()` to\n     * propagate child claims forward at mount time.\n     *\n     * Returned as `ReadonlySet` — callers must not mutate.\n     */\n    get pluginSingletons(): ReadonlySet<string> {\n        return this._pluginSingletons;\n    }\n\n    /**\n     * Register a route with the active router and record it on the\n     * App so `setRouter` / `use(child)` can read the canonical list\n     * back.\n     *\n     * @protected\n     */\n    protected register(route: Route<Handler>): void {\n        this.router.add(route);\n        this._routes.push(route);\n    }\n\n    /**\n     * Swap the active router. Replays every previously-registered\n     * route onto the new router so lookups stay correct.\n     *\n     * Useful for picking a router after route shape is known (e.g.\n     * a SmartRouter-style decision), or for testing alternatives\n     * mid-flight without rebuilding the App. Any cache the previous\n     * router carried is dropped along with it.\n     */\n    setRouter(router: IRouter<Handler>): void {\n        for (const route of this._routes) {\n            router.add(route);\n        }\n        this.router = router;\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: AppRequest): 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: AppRequest, 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    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        const savedAppOptions = event.appOptions;\n        const wasDispatching = event.isDispatching;\n\n        const isRoot = !wasDispatching;\n\n        event.appOptions = this._options;\n        event.isDispatching = true;\n\n        let response: Response | undefined;\n\n        try {\n            const matches = this.router.lookup(event.path, event.method);\n            response = await this.runMatches(event, matches, 0);\n\n            // OPTIONS auto-Allow synthesis — runs only on the root and\n            // only when no handler produced a response or an error.\n            if (\n                !event.error &&\n                !event.dispatched &&\n                isRoot &&\n                event.method === MethodName.OPTIONS\n            ) {\n                if (event.methodsAllowed.has(MethodName.GET)) {\n                    event.methodsAllowed.add(MethodName.HEAD);\n                }\n\n                const options = [...event.methodsAllowed]\n                    .map((key) => key.toUpperCase())\n                    .join(',');\n\n                const optionsHeaders = new Headers(event.response.headers);\n                optionsHeaders.set(HeaderName.ALLOW, options);\n                response = new Response(options, {\n                    status: event.response.status || 200,\n                    headers: optionsHeaders,\n                });\n\n                event.dispatched = true;\n            }\n        } finally {\n            event.appOptions = savedAppOptions;\n            event.isDispatching = wasDispatching;\n\n            // Restore routing state when this App did not produce a\n            // response, so a re-entrant dispatch caller (anyone\n            // invoking another App's `dispatch` on the same event\n            // afterwards) sees its own pre-dispatch state.\n            if (!event.dispatched) {\n                event.path = savedPath;\n                event.mountPath = savedMountPath;\n                event.params = savedParams;\n            }\n        }\n\n        return response;\n    }\n\n    /**\n     * Walk the matched routes for the current event, dispatching each\n     * handler in order. Re-entered (recursively) from the `setNext`\n     * continuation so `event.next()` resumes from the next match.\n     *\n     * The match list is captured once per dispatch — there is no\n     * mid-walk path-rewrite refresh. `IAppEvent.path` is a snapshot\n     * on the handler's facade event (see `event/module.ts`), so user\n     * middleware cannot mutate the dispatcher's path before calling\n     * `event.next()`. If a future API surface lets middleware rewrite\n     * paths end-to-end, this loop will need a per-call refresh + a\n     * `methodsAllowed` reset (see closed issue #913).\n     */\n    protected async runMatches(\n        event: IDispatcherEvent,\n        matches: readonly RouteMatch<Handler>[],\n        startIndex: number,\n    ): Promise<Response | undefined> {\n        let i = startIndex;\n        let response: Response | undefined;\n\n        while (!event.dispatched && i < matches.length) {\n            const match = matches[i]!;\n            const handler = match.route.data;\n\n            // Skip handlers that don't fit the current error state:\n            // CORE handlers only run when no error is pending;\n            // ERROR handlers only run when one is.\n            if (\n                (event.error && handler.type === HandlerType.CORE) ||\n                (!event.error && handler.type === HandlerType.ERROR)\n            ) {\n                i++;\n                continue;\n            }\n\n            const { method } = match.route;\n\n            if (method) {\n                event.methodsAllowed.add(method);\n            }\n\n            if (!matchHandlerMethod(method, event.method as MethodName)) {\n                i++;\n                continue;\n            }\n\n            mergeMatchParams(event, match.params);\n\n            // Surface the matched prefix as `event.mountPath` for the\n            // duration of this handler so static-asset / mount-aware\n            // helpers can strip it off `event.path`. Save and restore\n            // around the dispatch so siblings see their own prefixes.\n            const savedMountPath = event.mountPath;\n            if (typeof match.path === 'string') {\n                event.mountPath = match.path;\n            }\n\n            const capturedMatches = matches;\n            const nextIndex = i + 1;\n\n            event.setNext(async (error?: Error) => {\n                if (error) {\n                    event.error = createError(error);\n                }\n                return this.runMatches(event, capturedMatches, nextIndex);\n            });\n\n            try {\n                const dispatchResponse = await handler.dispatch(event);\n\n                if (dispatchResponse) {\n                    response = dispatchResponse;\n                    event.dispatched = true;\n                }\n            } catch (e) {\n                event.error = createError(e);\n                // Fall through to the next match — could be an error\n                // handler registered later in the chain.\n            } finally {\n                event.mountPath = savedMountPath;\n            }\n\n            i++;\n        }\n\n        return 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            // Check isHandler (instanceof brand) BEFORE isHandlerOptions\n            // (structural). Handler exposes `fn` and `type` as fields and\n            // would otherwise match the structural check and get wrapped\n            // into a fresh Handler with an empty config.\n            if (isHandler(element)) {\n                handler = element;\n            } else 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                });\n            } else {\n                continue;\n            }\n\n            this.register({\n                path: joinPaths(this._path, path, handler.path),\n                method,\n                data: handler,\n            });\n        }\n    }\n\n    // --------------------------------------------------\n\n    use(app: IApp): this;\n\n    use(handler: Handler | HandlerOptions): this;\n\n    use(plugin: Plugin): this;\n\n    use(path: Path, app: IApp): 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 (isAppInstance(item)) {\n                this.flatten(item, path);\n                continue;\n            }\n\n            // Check isHandler (instanceof brand) BEFORE isHandlerOptions\n            // (structural) — see useForMethod for the same reasoning.\n            if (isHandler(item)) {\n                this.register({\n                    path: joinPaths(this._path, path, item.path),\n                    method: item.method,\n                    data: item,\n                });\n                continue;\n            }\n\n            if (isHandlerOptions(item)) {\n                const handler = new Handler({ ...item });\n\n                this.register({\n                    path: joinPaths(this._path, path, handler.path),\n                    method: handler.method,\n                    data: handler,\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     * Snapshot a child App's routes and plugin registry into this\n     * one. Each route's path is prefixed with `this._path`, the\n     * supplied mount `path`, and the route's own path (in that\n     * order); the resulting entry is registered on this App's\n     * router. The child app is not retained — late mutations on it\n     * after this call do not propagate.\n     *\n     * @protected\n     */\n    protected flatten(child: IApp, path: Path | undefined): void {\n        // Routes always propagate — the child's plugin-registry\n        // bookkeeping is independent of which routes physically land on\n        // this App's router.\n        for (const route of child.routes) {\n            this.register({\n                path: joinPaths(this._path, path, route.path),\n                method: route.method,\n                data: route.data,\n            });\n        }\n\n        // Snapshot which plugin names this App already had *before* the\n        // merge. The sticky-claim propagation below uses this to honor\n        // the same first-install-wins rule `install()` enforces — a\n        // child's `singleton: true` claim must not retroactively lock a\n        // name the parent already installed non-singleton.\n        const namesBeforeMerge = new Set(this._plugins.keys());\n\n        // Merge the child's plugin registry. Each child key is in the\n        // child's canonical path space; composing with `this._path` +\n        // the mount `path` lifts it into our canonical space. The\n        // child's state is read through its public `plugins` /\n        // `pluginSingletons` getters — never the protected fields, so\n        // any future custom `IApp` only has to honor the public\n        // surface to be mountable.\n        //\n        // Note: this branch is intentionally asymmetric with\n        // `install()`. install() with `singleton: true` against an\n        // existing entry suppresses *both* the install and the claim.\n        // flatten() with a child-side sticky claim against an existing\n        // parent entry still merges the entry — child routes have\n        // already propagated unconditionally above, and suppressing\n        // the registry record too would leave `hasPluginAt` lying\n        // about routes that are demonstrably mounted.\n        for (const [name, childPaths] of child.plugins) {\n            // Sticky claim on this side blocks the merge of child's\n            // entries for that name. The claim is forward-looking; we\n            // don't drop the child's routes (registered above) — only\n            // the registry record so `hasPluginAt` reflects the locked\n            // namespace.\n            if (this._pluginSingletons.has(name)) {\n                continue;\n            }\n            let entry = this._plugins.get(name);\n            for (const [childKey, version] of childPaths) {\n                const composedKey = joinPaths(this._path, path, childKey) ?? '/';\n                // Silent dedup — first writer wins for the same\n                // composed key, mirroring `install()`'s silent skip.\n                if (entry && entry.has(composedKey)) {\n                    continue;\n                }\n                if (!entry) {\n                    entry = new Map();\n                    this._plugins.set(name, entry);\n                }\n                entry.set(composedKey, version);\n            }\n        }\n\n        // Propagate sticky singleton claims so a child's contract\n        // survives the mount — but only for names this App did not\n        // already have. Mirrors `install()`'s rule that a\n        // `singleton: true` install on a previously-claimed name is a\n        // silent no-op without claiming; flatten would otherwise leak\n        // child claims into a parent that had its own non-singleton\n        // install of the same name.\n        for (const name of child.pluginSingletons) {\n            if (!namesBeforeMerge.has(name)) {\n                this._pluginSingletons.add(name);\n            }\n        }\n    }\n\n    // --------------------------------------------------\n\n    /**\n     * Check if a plugin with the given name is installed on this App at\n     * *any* mount path.\n     */\n    hasPlugin(name: string): boolean {\n        const entry = this._plugins.get(name);\n        return !!entry && entry.size > 0;\n    }\n\n    /**\n     * Check if a plugin with the given name is installed at the given\n     * install-time `path`. `path` is interpreted the same way as the\n     * argument to `app.use(path, plugin)` — relative to this App. Omit\n     * `path` to check the root install.\n     */\n    hasPluginAt(name: string, path?: Path): boolean {\n        const entry = this._plugins.get(name);\n        if (!entry) {\n            return false;\n        }\n        const key = joinPaths(this._path, path) ?? '/';\n        return entry.has(key);\n    }\n\n    /**\n     * Get the version of an installed plugin by name, or `undefined`\n     * when the plugin is not installed. When the plugin is mounted at\n     * several paths, returns the version of an arbitrary mount —\n     * typical usage installs the same plugin object at every mount, so\n     * the version is identical. Use `getPluginVersionAt` to read the\n     * version of a specific mount.\n     */\n    getPluginVersion(name: string): string | undefined {\n        const entry = this._plugins.get(name);\n        if (!entry) {\n            return undefined;\n        }\n        const first = entry.values().next();\n        return first.done ? undefined : first.value;\n    }\n\n    /**\n     * Get the version of a plugin installed at the given install-time\n     * `path`, or `undefined` when no install matches. `path` is\n     * interpreted relative to this App (same convention as\n     * `app.use(path, plugin)`); omit it to read the root install.\n     */\n    getPluginVersionAt(name: string, path?: Path): string | undefined {\n        const entry = this._plugins.get(name);\n        if (!entry) {\n            return undefined;\n        }\n        return entry.get(joinPaths(this._path, path) ?? '/');\n    }\n\n    /**\n     * List every canonical mount path the named plugin is installed\n     * at. Returns an empty array when the plugin is not installed.\n     * Each path is the joined `app._path` + install-time path,\n     * normalized to `'/'` for root mounts.\n     */\n    getPluginMountPaths(name: string): readonly string[] {\n        const entry = this._plugins.get(name);\n        if (!entry) {\n            return [];\n        }\n        return Array.from(entry.keys());\n    }\n\n    // --------------------------------------------------\n\n    protected install(\n        plugin: Plugin,\n        context: PluginInstallContext = {},\n    ): this {\n        const mountKey = joinPaths(this._path, context.path) ?? '/';\n        const existing = this._plugins.get(plugin.name);\n\n        // Sticky claim: a previous successful `singleton: true` install\n        // locked this name. Every further install is a silent no-op so\n        // an idempotent `app.use(plugin)` is safe to call from setup\n        // code that doesn't know whether the plugin is already mounted.\n        if (this._pluginSingletons.has(plugin.name)) {\n            return this;\n        }\n\n        // This install opts into singleton but the name is already\n        // mounted at some path. Silent skip — we do *not* retroactively\n        // claim the name singleton, so a later non-flagged install of\n        // the same name can still succeed (first-install-wins).\n        if (plugin.singleton && existing && existing.size > 0) {\n            return this;\n        }\n\n        // SingletonByPath: silently skip a second install at the same\n        // canonical mount path. Installs at other paths still proceed.\n        if (plugin.singletonByPath && existing && existing.has(mountKey)) {\n            return this;\n        }\n\n        // Give the plugin its own App to install into so it can\n        // freely call `app.use(...)` / `app.get(...)` etc. without\n        // having to know whether the caller passed a path. We then\n        // mount this scratch app, which flattens its routes onto\n        // `this` and discards it.\n        const scratch = new App({ name: plugin.name });\n        plugin.install(scratch);\n\n        if (context.path) {\n            this.use(context.path, scratch);\n        } else {\n            this.use(scratch);\n        }\n\n        let entry = this._plugins.get(plugin.name);\n        if (!entry) {\n            entry = new Map();\n            this._plugins.set(plugin.name, entry);\n        }\n        entry.set(mountKey, plugin.version);\n\n        if (plugin.singleton) {\n            this._pluginSingletons.add(plugin.name);\n        }\n\n        return this;\n    }\n}\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,mBAAmB;;;;;;;;;;;AAYzB,IAAa,WAAb,MAA8C;CAC1C;CAEA,YAAY,UAA2B,EAAE,EAAE;EACvC,KAAK,QAAQ,IAAI,SAAoB,EAAE,SAAS,QAAQ,WAAW,kBAAkB,CAAC;;CAG1F,IAAI,KAA4B;EAC5B,OAAO,KAAK,MAAM,IAAI,IAAI;;CAG9B,IAAI,KAAa,OAAgB;EAC7B,KAAK,MAAM,IAAI,KAAK,MAAM;;CAG9B,OAAO,KAAmB;EACtB,KAAK,MAAM,OAAO,IAAI;;CAG1B,QAAc;EACV,KAAK,MAAM,OAAO;;;;;AC3C1B,MAAa,aAAa;CACtB,KAAK;CACL,MAAM;CACN,KAAK;CACL,OAAO;CACP,QAAQ;CACR,SAAS;CACT,MAAM;CACT;AAaD,MAAa,aAAa;CACtB,QAAQ;CACR,gBAAgB;CAChB,iBAAiB;CACjB,iBAAiB;CACjB,eAAe;CACf,OAAO;CACP,eAAe;CACf,qBAAqB;CACrB,kBAAkB;CAClB,gBAAgB;CAChB,eAAe;CACf,cAAc;CACd,YAAY;CACZ,QAAQ;CACR,MAAM;CACN,MAAM;CACN,mBAAmB;CACnB,eAAe;CACf,eAAe;CACf,UAAU;CACV,OAAO;CACP,kBAAkB;CAClB,sBAAsB;CACtB,kBAAkB;CAClB,aAAa;CACb,YAAY;CACZ,mBAAmB;CACnB,mBAAmB;CACnB,kBAAkB;CAClB,iBAAiB;CACjB,mBAAmB;CACtB;;;AC9BD,IAAa,WAAb,MAA2C;CACvC;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA,cAAwB;CAExB;CAEA;CAKA,YAAY,SAAgC;EACxC,KAAK,WAAW;EAChB,KAAK,UAAU,QAAQ;EACvB,KAAK,SAAS,QAAQ;EACtB,KAAK,OAAO,QAAQ;EACpB,KAAK,SAAS,QAAQ;EACtB,KAAK,YAAY,QAAQ;EACzB,KAAK,UAAU,QAAQ;EACvB,KAAK,eAAe,QAAQ;EAC5B,KAAK,WAAW,QAAQ;EACxB,KAAK,QAAQ,QAAQ;EACrB,KAAK,SAAS,QAAQ;EACtB,KAAK,aAAa,QAAQ;;CAG9B,IAAI,aAAsB;EACtB,OAAO,KAAK;;CAGhB,IAAI,aAAwD;EACxD,OAAO,KAAK;;CAGhB,iBAAgC;EAC5B,IAAI,CAAC,KAAK,qBAAqB;GAC3B,IAAI;GACJ,MAAM,UAAU,IAAI,SAAe,MAAM;IAAE,UAAU;KAAK;GAC1D,KAAK,sBAAsB;IAAE;IAAS;IAAS;GAE/C,IAAI,KAAK,aACL,SAAS;;EAIjB,OAAO,KAAK,oBAAoB;;CAGpC,MAAM,KAAK,OAA8C;EACrD,IAAI,KAAK,aACL,OAAO,KAAK;EAGhB,KAAK,cAAc;EACnB,KAAK,cAAc,KAAK,SAAS,KAAK,MAAM,MAAM;EAElD,IAAI,KAAK,qBACL,KAAK,oBAAoB,SAAS;EAGtC,OAAO,KAAK;;;;;AClGpB,SAAgB,wBAAwB,OAAkB,SAAuC;CAC7F,UAAU,WAAW,EAAE;CAEvB,MAAM,gBAAgB,CAAC,SAAS,CAAC,OAAO,QAAQ,iBAAiB,EAAE,CAAC;CAEpE,IAAI,QAAQ,WAAW,KAAA,GACnB,cAAc,KAAK,WAAW,CAAC,QAAQ,UAAU,YAAY,CAAC,QAAQ,SAAS;CAGnF,IAAI,QAAQ,cAAc;EACtB,MAAM,eAAe,OAAO,QAAQ,iBAAiB,WACjD,IAAI,KAAK,QAAQ,aAAa,GAC9B,QAAQ;EAEZ,MAAM,SAAS,QAAQ,IAAI,iBAAiB,aAAa,aAAa,CAAC;;CAG3E,MAAM,SAAS,QAAQ,IAAI,iBAAiB,cAAc,KAAK,KAAK,CAAC;;;;ACnBzE,MAAa,cAAc,OAAO,IAAI,WAAW;AAEjD,IAAa,WAAb,cAA8B,UAAU;CACpC,YAAY,QAAwB,EAAE,EAAE;EACpC,MAAM,MAAM;EACZ,KAAK,OAAO;EACZ,eAAe,MAAM,YAAY;;;;;ACVzC,SAAS,cAAc,OAAwB;CAC3C,OAAO,MAAM,QAAQ,WAAW,GAAG;;AAGvC,SAAgB,4BAA4B,SAAqC;CAC7E,IAAI,SAAS;CAEb,IAAI,QAAQ,IACR,UAAU,OAAO,cAAc,QAAQ,GAAG,CAAC;CAG/C,IAAI,QAAQ,OACR,UAAU,UAAU,cAAc,QAAQ,MAAM,CAAC;CAGrD,IACI,OAAO,QAAQ,UAAU,YACzB,OAAO,UAAU,QAAQ,MAAM,EAE/B,UAAU,UAAU,QAAQ,MAAM;CAGtC,MAAM,QAAQ,QAAQ,KAAK,QAAQ,OAAO,GAAG,CAAC,MAAM,KAAK;CACzD,KAAK,MAAM,QAAQ,OACf,UAAU,SAAS,KAAK;CAE5B,UAAU;CAEV,OAAO;;;;ACdX,SAAgB,kBACZ,OACA,SACiB;CACjB,IAAI,SAAS,mBAAmB,KAAA;MACxB,CAAC,OAAO,UAAU,QAAQ,eAAe,IAAI,QAAQ,iBAAiB,GACtE,MAAM,IAAI,SAAS,iDAAiD;;CAI5E,IAAI;CACJ,IAAI,SAAS;CACb,MAAM,UAAU,IAAI,aAAa;CAEjC,MAAM,SAAS,IAAI,eAA2B;EAC1C,MAAM,MAAM;GACR,aAAa;;EAEjB,SAAS;GACL,SAAS;;EAEhB,CAAC;CAEF,MAAM,UAAU,IAAI,QAAQ,MAAM,SAAS,QAAQ;CACnD,QAAQ,IAAI,WAAW,cAAc,oBAAoB;CACzD,QAAQ,IAAI,WAAW,eAAe,wEAAwE;CAC9G,QAAQ,IAAI,WAAW,mBAAmB,KAAK;CAC/C,QAAQ,IAAI,WAAW,YAAY,aAAa;CAOhD,MAAM,SAA4B;EAC9B,MAAM,SAA+C;GACjD,IAAI,QAAQ,OAAO;GAEnB,IAAI,OAAO,YAAY,UACnB,OAAO,OAAO,MAAM,EAAE,MAAM,SAAS,CAAC;GAG1C,MAAM,aAAa,4BAA4B,QAAQ;GAEvD,IAAI,SAAS,mBAAmB,KAAA;QACL,QAAQ,OAAO,WAAW,CAAC,aAC7B,QAAQ,gBACzB,OAAO;;GAIf,WAAW,QAAQ,QAAQ,OAAO,WAAW,CAAC;GAC9C,OAAO;;EAGX,MAAY;GACR,IAAI,QAAQ;GAEZ,SAAS;GACT,WAAW,OAAO;;EAGtB,UAAA,IAjCiB,SAAS,QAAQ;GAClC,QAAQ,MAAM,SAAS;GACvB;GACH,CA8BW;EACX;CAED,OAAO;;;;;;;;;;;;;;ACvEX,SAAgB,YAAY,SAA2B;CACnD,MAAM,SAAS,QAAQ,QAAQ,IAAI,SAAS;CAC5C,IAAI,CAAC,QACD,OAAO;CAGX,OAAO,OACF,aAAa,CACb,MAAM,IAAI,CACV,MAAM,UAAU;EACb,MAAM,QAAQ,MAAM,MAAM,IAAI,CAAC,KAAK,SAAS,KAAK,MAAM,CAAC;EACzD,MAAM,aAAa,MAAM;EAGzB,MAAM,SAAS,MAAM,MAAM,EAAE,CACxB,KAAK,UAAU,MAAM,MAAM,IAAI,CAAC,KAAK,MAAM,EAAE,MAAM,CAAC,CAAC,CACrD,MAAM,CAAC,SAAS,QAAQ,IAAI;EACjC,MAAM,IAAI,SAAS,OAAO,WAAW,OAAO,MAAM,GAAG,GAAG;EACxD,IAAI,CAAC,OAAO,SAAS,EAAE,IAAI,KAAK,GAC5B,OAAO;EAGX,OAAO,eAAe,SAClB,eAAe,mBACf,eAAe,sBACf,WAAW,SAAS,QAAQ;GAClC;;;;ACpCV,SAAgB,oBAAoB,OAAwB;CACxD,OAAO,MAAM,QAAQ,WAAW,GAAG;;;;ACEvC,eAAe,KAAK,KAA+B;CAC/C,MAAM,MAAM,IAAI,aAAa;CAC7B,MAAM,OAAO,MAAM,OAAO,OAAO,SAAS,IAAI,OAAO,IAAI,CAAC;CAE1D,OAAO,KAAK,OAAO,aAAa,GAAG,IAAI,WAAW,KAAK,CAAC,CAAC;;;;;AAM7D,eAAsB,aAAa,OAAiC;CAChE,IAAI,MAAM,WAAW,GAEjB,OAAO;CAGX,MAAM,OAAO,MAAM,KAAK,MAAM;CAE9B,OAAO,IAAI,MAAM,OAAO,SAAS,GAAG,CAAC,GAAG,KAAK,UAAU,GAAG,GAAG,CAAC;;;;;AAMlE,eAAsB,WAClB,OACA,UAAuB,EAAE,EACT;CAEhB,MAAM,MAAM,MAAM,aAAa,MAAM;CAErC,OAAO,QAAQ,OACX,KAAK,QACL;;;;ACpCR,SAAgB,SAAS,MAA6C;CAClE,OACI,CAAC,CAAC,QACF,OAAO,SAAS,YAChB,CAAC,MAAM,QAAQ,KAAK;;;;ACC5B,MAAM,8BAA8B,IAAI,aAAa;AAErD,SAAgB,YAAY,OAAiD;CACzE,IAAI,OAAO,UAAU,YACjB,OAAO;CAGX,QAAQ,SAAS;CAEjB,IAAI,UAAU,OACV,aAAa,QAAQ,QAAQ,KAAA,EAAU;CAG3C,IAAI,UAAwB,EAAE,MAAM,MAAM;CAE1C,IAAI,SAAS,MAAM,EACf,UAAU,MAAM,OAAO,QAAQ;CAGnC,OAAO,OAAO,MAAc,SAAkB;EAC1C,IAAI,OAAO,QAAQ,cAAc;QACZ,QAAQ,YAAY,OAAO,KAAK,CAAC,eAElC,QAAQ,WACpB;;EAIR,OAAO,WAAW,MAAM,QAAQ;;;;;;;;;;;;AAaxC,MAAa,kBAA0B,aAAa;;;AC3CpD,SAAgB,kBACZ,OACa;CACb,IAAI,OAAO,UAAU,YACjB,OAAO;CAGX,IAAI,UAAU,MACV,aAAa;CAGjB,IAAI,OAAO,UAAU,UACjB,QAAQ,UAAU,QAAQ,MAAO;CAGrC,IAAI,OAAO,UAAU,UACjB,QAAQ,MAAM,MAAM,IAAI,CACnB,KAAK,UAAU,MAAM,MAAM,CAAC;CAGrC,OAAO,QAAQ,SAAS,EAAE,CAAC;;;;;;;;;;AAW/B,MAAa,sBAAoC,mBAAmB;;;AChCpE,SAAgB,YAAY,MAAmC;CAC3D,IAAI,KAAK,SAAS,IAAI,EAClB,OAAO;CAGX,OAAO,QAAQ,KAAK;;AAGxB,SAAgB,sBAAsB,MAAmC;CACrE,IAAK,0CAA2C,KAAK,KAAK,EACtD,OAAO;CAGX,MAAM,OAAO,IAAI,KAAK;CACtB,IACI,QACA,KAAK,SAEL,OAAO,KAAK,QAAQ,aAAa;;;;AChBzC,SAAgB,aACZ,OACA,KACuB;CACvB,IAAI,OACA,OAAO,MAAM,aAAa;CAG9B,OAAO;;;;;;;ACRX,SAAS,qBAAqB,QAAQ,IAAI;CACtC,IAAI,CAAC,SAAS,CAAC,MAAM,SAAS,KAAK,EAC/B,OAAO;CAGX,OAAO,MAAM,QAAQ,OAAO,IAAI;;AAGpC,MAAM,aAAa;AACnB,SAAgB,QAAQ,OAAe;CACnC,MAAM,QAAQ,WAAW,KAAK,qBAAqB,MAAM,CAAC;CAC1D,OAAQ,SAAS,MAAM,MAAO;;AAGlC,SAAgB,SAAS,OAAe,WAAoB;CACxD,MAAM,cAAc,qBAAqB,MAAM,CAC1C,MAAM,IAAI,CACV,KAAK;CAEV,IAAI,CAAC,aACD,OAAO;CAGX,OAAO,aAAa,YAAY,SAAS,UAAU,GAC/C,YAAY,MAAM,GAAG,CAAC,UAAU,OAAO,GACvC;;;;AC3BR,SAAgB,UAAU,GAAoC;CAC1D,OAAO,SAAS,EAAE,KAEV,aAAa,WAGb,OAAO,EAAE,SAAS;;;;AC6B9B,SAAgB,gBAAgB,QAAQ,IAAa;CACjD,OAAO,MAAM,WAAW,IAAI;;AAOhC,SAAgB,iBAAiB,QAAQ,IAAY;CACjD,OAAO,gBAAgB,MAAM,GAAG,QAAQ,IAAI;;AAGhD,SAAgB,mBAAmB,QAAQ,IAAY;CACnD,IAAI,MAAM,SAAS,MAAM,EACrB,OAAO,MAAM,MAAM,MAAM,CACpB,KAAK,QAAQ,mBAAmB,IAAI,CAAC,CACrC,KAAK,MAAM;CAGpB,OAAO,MAAM,QAAQ,QAAQ,IAAI;;;;;;;;;;;;;;;;;;AAmBrC,SAAgB,UAAU,GAAG,OAAsD;CAC/E,MAAM,OAAiB,EAAE;CACzB,KAAK,MAAM,QAAQ,OAAO;EACtB,IAAI,OAAO,SAAS,YAAY,SAAS,IACrC;EAEJ,KAAK,KAAK,KAAK;;CAEnB,IAAI,KAAK,WAAW,GAChB;CAEJ,MAAM,aAAa,mBAAmB,iBAAiB,KAAK,KAAK,IAAI,CAAC,CAAC;CACvE,IAAI,WAAW,SAAS,KAAK,WAAW,SAAS,IAAI,EACjD,OAAO,WAAW,MAAM,GAAG,GAAG;CAElC,OAAO;;;;ACvFX,SAAgB,qBACZ,OACA,MACA,OACF;CACE,MAAM,EAAE,YAAY,MAAM;CAE1B,IAAI,MAAM,QAAQ,MAAM,EACpB,KAAK,MAAM,KAAK,OACZ,QAAQ,OAAO,MAAM,oBAAoB,EAAE,CAAC;MAGhD,QAAQ,OAAO,MAAM,oBAAoB,MAAM,CAAC;;AAIxD,SAAgB,8BACZ,OACA,MACA,OACF;CACE,MAAM,EAAE,YAAY,MAAM;CAC1B,MAAM,WAAW,QAAQ,IAAI,KAAK;CAElC,IAAI,CAAC,UAAU;EACX,IAAI,MAAM,QAAQ,MAAM,EACpB,QAAQ,IAAI,MAAM,oBAAoB,MAAM,KAAK,KAAK,CAAC,CAAC;OAExD,QAAQ,IAAI,MAAM,oBAAoB,MAAM,CAAC;EAEjD;;CAGJ,MAAM,aAAa,SAAS,MAAM,KAAK;CAEvC,IAAI,MAAM,QAAQ,MAAM,EACpB,WAAW,KAAK,GAAG,MAAM;MAEzB,WAAW,KAAK,MAAM;CAG1B,MAAM,SAAS,CAAC,GAAG,IAAI,IAAI,WAAW,CAAC;CAEvC,QAAQ,IAAI,MAAM,oBAAoB,OAAO,KAAK,KAAK,CAAC,CAAC;;;;AC1C7D,SAAgB,iCAAiC,OAAkB,UAAkB;CACjF,MAAM,MAAM,QAAQ,SAAS;CAC7B,IAAI,KAAK;EACL,IAAI,OAAO,YAAY,IAAI,UAAU,EAAE,CAAC;EACxC,IAAI,MAAM;GACN,MAAM,UAAU,sBAAsB,KAAK;GAC3C,IAAI,SACA,QAAQ,aAAa;GAEzB,MAAM,SAAS,QAAQ,IAAI,WAAW,cAAc,KAAK;;;;;;ACRrE,MAAM,8BAA8B;AACpC,MAAM,mBAAmB;AACzB,MAAM,eAAe;AACrB,MAAM,oBAAoB;AAC1B,MAAM,oBAAoB;AAC1B,MAAM,eAAe;AAErB,SAAS,QAAQ,MAAsB;CACnC,OAAO,IAAI,KAAK,WAAW,EAAE,CAAC,SAAS,GAAG,CAAC,aAAa;;AAG5D,SAAS,YAAY,OAAuB;CACxC,OAAO,IAAI,MAAM,QAAQ,cAAc,OAAO,CAAC;;AAGnD,SAAS,SAAS,OAAuB;CACrC,OAAO,MAAM,QAAQ,kBAAkB,IAAI;;AAG/C,SAAS,eAAe,OAAuB;CAC3C,OAAO,mBAAmB,MAAM,CAAC,QAAQ,6BAA6B,QAAQ;;AAGlF,SAAS,eAAe,OAAuB;CAC3C,IAAI,aAAa,KAAK,MAAM,EACxB,OAAO,YAAY;CAEvB,OAAO,YAAY,YAAY,MAAM;;AAGzC,SAAS,eACL,OACA,MACA,UACF;CACE,IAAI,cAAsB;CAE1B,IAAI,OAAO,aAAa,UAAU;EAC9B,iCAAiC,OAAO,SAAS;EAKjD,IAHoB,kBAAkB,KAAK,SAAS,IAChD,CAAC,kBAAkB,KAAK,SAAS,EAGjC,eAAe,KAAK,eAAe,SAAS;OACzC;GACH,eAAe,KAAK,eAAe,SAAS,SAAS,CAAC;GACtD,eAAe,sBAAsB,eAAe,SAAS;;;CAIrE,MAAM,SAAS,QAAQ,IACnB,WAAW,qBACX,YACH;;AAGL,SAAgB,4BAA4B,OAAkB,UAAmB;CAC7E,eAAe,OAAO,cAAc,SAAS;;AAGjD,SAAgB,wBAAwB,OAAkB,UAAmB;CACzE,eAAe,OAAO,UAAU,SAAS;;;;AC/D7C,SAAgB,6BAA6B,OAAkB,OAAe,aAAuB;CACjG,IAAI;MACe,MAAM,SAAS,QAAQ,IAAI,WAAW,aAC3C,EACN;;CAIR,MAAM,cAAc,YAAY,MAAM;CACtC,IAAI,aACA,MAAM,SAAS,QAAQ,IAAI,WAAW,cAAc,YAAY;;;;AC+BxE,eAAsB,SAClB,OACA,SACkB;CAClB,IAAI;CACJ,IAAI,OAAO,QAAQ,UAAU,YACzB,QAAQ,MAAM,QAAQ,OAAO;MAE7B,QAAQ,QAAQ;CAGpB,MAAM,OAAO,QAAQ,QAAQ,MAAM;CACnC,MAAM,EAAE,YAAY,MAAM;CAE1B,MAAM,cAAc,QAAQ,gBAAgB,QAAQ,aAAa,eAAe,KAAA;CAEhF,IAAI,MAAM;EACN,MAAM,WAAW,SAAS,KAAK;EAE/B,IAAI;OAEI,CADsB,QAAQ,IAAI,WAAW,oBAC3B,EAClB,IAAI,gBAAgB,UAChB,wBAAwB,OAAO,SAAS;QAExC,4BAA4B,OAAO,SAAS;SAIpD,iCAAiC,OAAO,SAAS;;CAIzD,MAAM,iBAA0C,EAAE;CAClD,IAAI,aAAa,MAAM,SAAS;CAEhC,IAAI,MAAM,MAAM;EACZ,MAAM,cAAc,MAAM,QAAQ,IAAI,WAAW,MAAM;EACvD,IAAI,aAAa;GACb,MAAM,CAAC,GAAG,KAAK,YAAY,QAAQ,UAAU,GAAG,CAC3C,MAAM,IAAI;GAEf,MAAM,cAAc,OAAO,SAAS,GAAG,GAAG;GAC1C,MAAM,YAAY,OAAO,SAAS,GAAG,GAAG;GAExC,eAAe,QAAQ,OAAO,SAAS,YAAY,IAAI,eAAe,IAAI,cAAc;GACxF,eAAe,MAAM,OAAO,SAAS,UAAU,IAAI,aAAa,IAC5D,KAAK,IAAI,WAAW,MAAM,OAAO,EAAE,GACnC,MAAM,OAAO;GAEjB,IACI,eAAe,SAAS,MAAM,QAC9B,eAAe,QAAQ,eAAe,KACxC;IACE,MAAM,eAAe,IAAI,QAAQ,QAAQ;IACzC,aAAa,IAAI,WAAW,eAAe,WAAW,MAAM,OAAO;IACnE,OAAO,IAAI,SAAS,MAAM;KACtB,QAAQ;KACR,SAAS;KACZ,CAAC;;GAGN,QAAQ,IAAI,WAAW,eAAe,SAAS,eAAe,MAAM,GAAG,eAAe,IAAI,GAAG,MAAM,OAAO;GAC1G,QAAQ,IAAI,WAAW,gBAAgB,GAAG,eAAe,MAAM,eAAe,QAAQ,IAAI;GAC1F,aAAa;SAEb,QAAQ,IAAI,WAAW,gBAAgB,GAAG,MAAM,OAAO;EAG3D,QAAQ,IAAI,WAAW,eAAe,QAAQ;EAE9C,IAAI,MAAM,OAAO;GACb,MAAM,QAAQ,IAAI,KAAK,MAAM,MAAM;GACnC,QAAQ,IAAI,WAAW,eAAe,MAAM,aAAa,CAAC;GAC1D,QAAQ,IAAI,WAAW,MAAM,MAAM,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,GAAG;;;CAI5E,MAAM,UAAU,MAAM,QAAQ,QAAQ,eAAe;CAErD,OAAO,IAAI,SAAS,SAAqB;EACrC,QAAQ;EACR;EACH,CAAC;;;;AC9HN,SAAgB,iBACZ,OACA,MACc;CACd,OAAO,MAAM,QAAQ,IAAI,KAAK;;;;ACFlC,MAAM,iBAAiB,OAAO,IAAI,oBAAoB;AAEtD,SAAS,qBAAqB,SAA2C;CACrE,MAAM,SAAiC,EAAE;CACzC,QAAQ,SAAS,OAAO,QAAQ;EAC5B,OAAO,OAAO;GAChB;CACF,OAAO;;AAGX,SAAgB,qBAAqB,OAA+B;CAChE,IAAI,QAAQ,MAAM,MAAM;CACxB,IAAI,OACA,OAAO;CAGX,QAAQ,IAAI,WAAW,EAAE,SAAS,qBAAqB,MAAM,QAAQ,EAAE,CAAC;CACxE,MAAM,MAAM,kBAAkB;CAC9B,OAAO;;;;AChBX,SAAgB,iCAAiC,OAA6B;CAG1E,OAFmB,qBAAqB,MAEvB,CAAC,YAAY;;AAGlC,SAAgB,gCAAgC,OAAkB,OAAgD;CAC9G,QAAQ,SAAS,EAAE;CAEnB,MAAM,QAAQ,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM;CAEpD,IAAI,MAAM,WAAW,GACjB,OAAO,iCAAiC,MAAM,CAAC,OAAO;CAI1D,IAAI,CADW,iBAAiB,OAAO,WAAW,OACvC,EACP,OAAO,MAAM;CAGjB,IAAI,WAAW;CACf,MAAM,YAAuB,EAAE;CAC/B,KAAK,MAAM,QAAQ,OAAO;EACtB,MAAM,WAAW,YAAY,KAAK;EAClC,IAAI,UACA,UAAU,KAAK,SAAS;OAExB,WAAW;;CAKnB,MAAM,UADa,qBAAqB,MACd,CAAC,WAAW,UAAU;CAChD,IAAI,QAAQ,SAAS,GAAG;EACpB,IAAI,UACA,OAAO,MAAM;EAGjB,OAAO,MAAM,UAAU,QAAQ,QAAQ,GAAI;;;;;AClCnD,SAAgB,WAAW,OAAkB,OAAwD;CACjG,MAAM,EACF,SAAS,eACT,GAAG,YACH;CAEJ,MAAM,eAAe,OAAO,KAAK,QAAQ;CAEzC,IAAI,aAAa,WAAW,GACxB,OAAO,eAAe;CAG1B,MAAM,cAAc,gCAAgC,OAAO,aAAa;CACxE,IAAI,eAAe,QAAQ,cACvB,OAAO,QAAQ,cAAc;CAGjC,OAAO,eAAe;;;;ACvB1B,SAAS,WAAW,KAAsB;CACtC,OAAO,IACF,QAAQ,MAAM,QAAQ,CACtB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,SAAS;;AAGhC,SAAS,qBAAqB,UAA4B;CAEtD,IAAI,SAAS,WAAW,KAAK,EACzB,OAAO;CAGX,IAAI,SAAS,WAAW,IAAI,IAAI,SAAS,WAAW,IAAI,EACpD,OAAO;CAGX,IAAI;EACA,MAAM,MAAM,IAAI,IAAI,SAAS;EAC7B,OAAO,IAAI,aAAa,WAAW,IAAI,aAAa;SAChD;EACJ,OAAO;;;AAIf,SAAgB,aAAa,OAAkB,UAAkB,aAAa,KAAe;CACzF,IAAI,CAAC,qBAAqB,SAAS,EAC/B,MAAM,IAAI,SAAS;EACf,QAAQ;EACR,SAAS;EACZ,CAAC;CAGN,MAAM,oBAAoB,oBAAoB,SAAS;CAEvD,MAAM,OAAO,yEADM,WAAW,SACkE,CAAC;CAEjG,MAAM,UAAU,IAAI,QAAQ,MAAM,SAAS,QAAQ;CACnD,QAAQ,IAAI,YAAY,kBAAkB;CAC1C,QAAQ,IAAI,gBAAgB,2BAA2B;CACvD,QAAQ,OAAO,iBAAiB;CAOhC,OAAO,IALc,SAAS,MAAM;EAChC,QAAQ;EACR;EACH,CAEc;;;;AClDnB,SAAgB,WAAW,OAAkB,QAAkC;CAC3E,MAAM,EACF,QACA,YACA,MAAM;CAEV,OAAO,IAAI,SAAS,QAAQ;EACxB;EACA;EACH,CAAC;;;;ACPN,SAAgB,QAAQ,OAAoC;CACxD,OAAO,cAAc,OAAO,YAAY;;;;ACC5C,SAAS,cAAc,OAAgC;CACnD,OAAO,SAAS,MAAM,IAClB,OAAQ,MAAkC,YAAY,YACtD,OAAQ,MAAkC,SAAS;;;;;;;;;;;;AAa3D,SAAgB,YAAY,OAA4C;CACpE,IAAI,QAAQ,MAAM,EACd,OAAO;CAGX,IAAI,OAAO,UAAU,UACjB,OAAO,IAAI,SAAS,MAAM;CAG9B,IAAI,YAAY,MAAM,EAClB,OAAO,IAAI,SAAS;EAChB,SAAS,MAAM;EACf,MAAM,MAAM;EACZ,QAAQ,MAAM;EACd,aAAa,MAAM;EACnB,OAAO;EACV,CAAC;CAGN,IAAI,cAAc,MAAM,EACpB,OAAO,IAAI,SAAS;EAChB,SAAS,MAAM;EACf,OAAO;EACV,CAAC;CAGN,IAAI,CAAC,SAAS,MAAM,EAChB,OAAO,IAAI,UAAU;CAGzB,MAAM,UAAU,EAAE,GAAG,OAAkC;CACvD,IAAI,QAAQ,UAAU,KAAA,GAClB,QAAQ,QAAQ;CAGpB,OAAO,IAAI,SAAS,QAA0B;;;;ACpDlD,SAAS,gBAAgB,MAAsB;CAC3C,OAAO,KAAK,WAAW,KAAK,GAAG,KAAK,MAAM,EAAE,GAAG;;;;;;;;AASnD,SAAS,gBAAgB,OAAiC;CACtD,MAAM,MAAM,MAAM,WAAW;CAC7B,IAAI,QAAQ,MAAM,OAAO;CACzB,IAAI,OAAO,QAAQ,aAAa,OAAO;CACvC,OAAO;;;;;;;;AASX,eAAe,UACX,MACA,OACA,SAC6B;CAG7B,MAAM,SAAS,gBAAgB,MAAM;CACrC,IAAI,CAAC,QACD;CAGJ,MAAM,OAAO,MAAM,OAAO,KAAK;CAC/B,IAAI,CAAC,MACD;CAGJ,QAAQ,IAAI,QAAQ,KAAK;CAEzB,MAAM,cAAc,MAAM,QAAQ,IAAI,gBAAgB;CACtD,IAAI,gBAAgB,gBAAgB,OAAO,YAAY,MAAM,IAAI,CAAC,MAAM,MAAM,gBAAgB,EAAE,MAAM,CAAC,KAAK,gBAAgB,KAAK,CAAC,GAC9H,OAAO,IAAI,SAAS,MAAM;EACtB,QAAQ;EACR;EACH,CAAC;;;;;;;;;;;;;;AAkBV,SAAgB,WACZ,OACA,OACoD;CAEpD,IAAI,UAAU,KAAA,GACV;CAGJ,IAAI,UAAU,MACV,OAAO,IAAI,SAAS,MAAM;EACtB,QAAQ,MAAM,SAAS;EACvB,SAAS,MAAM,SAAS;EAC3B,CAAC;CAON,MAAM,IAAI,OAAO;CAEjB,IAAI,MAAM,UAAU;EAChB,MAAM,EAAE,QAAQ,YAAY,MAAM;EAClC,IAAI,CAAC,QAAQ,IAAI,eAAe,EAC5B,QAAQ,IAAI,gBAAgB,4BAA4B;EAK5D,IAAI,MAAM,WAAW,SAAS,MAC1B,OAAO,UAAU,OAAiB,OAAO,QAAQ,CAC5C,MAAM,WAAW,UAAU,IAAI,SAAS,OAAiB;GACtD;GACA;GACH,CAAC,CAAC;EAGX,OAAO,IAAI,SAAS,OAAiB;GACjC;GACA;GACH,CAAC;;CAGN,IACI,MAAM,YACN,CAAC,MAAM,QAAQ,MAAM,EACvB;EAME,IAAI,iBAAiB,UACjB,OAAO;EAGX,MAAM,EAAE,QAAQ,YAAY,MAAM;EAIlC,IAAI,iBAAiB,eAAe,iBAAiB,YAAY;GAC7D,IAAI,CAAC,QAAQ,IAAI,eAAe,EAC5B,QAAQ,IAAI,gBAAgB,2BAA2B;GAE3D,OAAO,IAAI,SAAS,OAAmB;IACnC;IACA;IACH,CAAC;;EAGN,IAAI,iBAAiB,gBACjB,OAAO,IAAI,SAAS,OAAO;GACvB;GACA;GACH,CAAC;EAGN,IAAI,iBAAiB,MAAM;GACvB,IAAI,CAAC,QAAQ,IAAI,eAAe,EAC5B,QAAQ,IAAI,gBAAgB,MAAM,QAAQ,2BAA2B;GAEzE,OAAO,IAAI,SAAS,OAAO;IACvB;IACA;IACH,CAAC;;;CAIV,MAAM,EAAE,QAAQ,YAAY,MAAM;CAClC,IAAI,CAAC,QAAQ,IAAI,eAAe,EAC5B,QAAQ,IAAI,gBAAgB,kCAAkC;CAGlE,IAAI;CACJ,IAAI;EACA,OAAO,KAAK,UAAU,MAAM;UACvB,GAAG;EACR,MAAM,YAAY;GACd,SAAS;GACT,QAAQ;GACR,OAAO;GACV,CAAC;;CAGN,IAAI,MAAM,WAAW,SAAS,MAC1B,OAAO,UAAU,MAAM,OAAO,QAAQ,CACjC,MAAM,WAAW,UAAU,IAAI,SAAS,MAAM;EAC3C;EACA;EACH,CAAC,CAAC;CAGX,OAAO,IAAI,SAAS,MAAM;EACtB;EACA;EACH,CAAC;;;;AC3KN,IAAa,kBAAb,MAAyD;CACrD;CAEA;CAEA;CAEA;;;;CAKA;CAEA;CAEA;;;;;;;;CASA;;;;;;;CAQA;CAEA;CAEA;CAEA;;;;CAKA;;;;CAKA;CAEA;CAEA;;;;CAKA;;;;CAKA;CAIA,YAAY,SAAqB;EAC7B,KAAK,UAAU;EACf,KAAK,OAAO,IAAI,QAAQ,QAAQ,IAAI;EACpC,KAAK,SAAS,QAAQ;EACtB,KAAK,OAAO,KAAK,KAAK;EACtB,KAAK,YAAY;EACjB,KAAK,SAAS,EAAE;EAChB,KAAK,aAAa,EAAE;EACpB,KAAK,gBAAgB;EACrB,KAAK,iCAAiB,IAAI,KAAK;EAC/B,KAAK,cAAc;EACnB,KAAK,cAAc;;CAKvB,IAAI,WAAwB;EACxB,IAAI,CAAC,KAAK,WACN,KAAK,YAAY;GAAE,QAAQ;GAAK,SAAS,IAAI,SAAS;GAAE;EAG5D,OAAO,KAAK;;CAGhB,IAAI,SAAsB;EACtB,IAAI,CAAC,KAAK,SACN,KAAK,UAAU,KAAK,QAAQ;EAGhC,OAAO,KAAK;;CAGhB,IAAI,OAAO,OAAoB;EAE3B,IAAI,KAAK,gBAAgB;GACrB,KAAK,gBAAgB;GACrB,KAAK,iBAAiB,KAAA;;EAG1B,IAAI,UAAU,KAAK,QAAQ,QAAQ;GAC/B,KAAK,UAAU;GACf;;EAGJ,MAAM,aAAa,IAAI,iBAAiB;EACxC,MAAM,SAAS,MAAc;GACzB,MAAM,SAAS,GAAG,kBAAkB,cAChC,EAAE,OAAO,SACT,KAAA;GACJ,KAAK,QAAQ,OAAO,oBAAoB,SAAS,MAAM;GACvD,MAAM,oBAAoB,SAAS,MAAM;GACzC,WAAW,MAAM,OAAO;;EAG5B,IAAI,KAAK,QAAQ,OAAO,WAAW,MAAM,SAAS;GAC9C,MAAM,SAAS,KAAK,QAAQ,OAAO,UAC/B,KAAK,QAAQ,OAAO,SACpB,MAAM;GACV,WAAW,MAAM,OAAO;SACrB;GACH,KAAK,QAAQ,OAAO,iBAAiB,SAAS,OAAO,EAAE,MAAM,MAAM,CAAC;GACpE,MAAM,iBAAiB,SAAS,OAAO,EAAE,MAAM,MAAM,CAAC;GACtD,KAAK,uBAAuB;IACxB,KAAK,QAAQ,OAAO,oBAAoB,SAAS,MAAM;IACvD,MAAM,oBAAoB,SAAS,MAAM;;;EAIjD,KAAK,UAAU,WAAW;;CAG9B,IAAI,aAAsB;EACtB,OAAO,KAAK;;CAGhB,IAAI,WAAW,OAAgB;EAC3B,KAAK,cAAc;;CAKvB,MAAgB,KAAK,OAAkB,OAA8C;EACjF,IAAI,KAAK,aACL,OAAO,KAAK;EAEhB,KAAK,cAAc;EAEnB,IAAI,KAAK,OACL,KAAK,cAAc,KAAK,MAAM,OAAO,MAAM;EAG/C,OAAO,KAAK;;CAGhB,QAAQ,IAAmB;EACvB,IAAI,IACA,KAAK,QAAQ,OAAO,OAAO,UAAkB;GAEzC,OAAO,WAAW,MADG,GAAG,MAAM,EACJ,MAAM;;OAGpC,KAAK,QAAQ,KAAA;EAGjB,KAAK,cAAc;EACnB,KAAK,cAAc,KAAA;;CAKvB,MAAM,QAAgC;EAClC,OAAO,IAAI,SAAS;GAChB,SAAS,KAAK;GACd,QAAQ,KAAK;GACb,MAAM,KAAK;GACX,QAAQ,KAAK;GACb,WAAW,KAAK;GAChB,SAAS,KAAK,QAAQ;GACtB,cAAc,IAAI,gBAAgB,KAAK,KAAK,OAAO;GACnD,UAAU,KAAK;GACf,OAAO,KAAK;GACZ,QAAQ,UAAU,KAAK;GACvB,YAAY,KAAK;GACjB,OAAO,OAAkB,UAAkB,KAAK,KAAK,OAAO,MAAM;GACrE,CAAC;;CAKN,IAAc,QAA0C;EACpD,IAAI,CAAC,KAAK,QACN,KAAK,SAAS,OAAO,OAAO,KAAK;EAGrC,OAAO,KAAK;;;;;ACxNpB,MAAa,cAAc;CACvB,MAAM;CACN,OAAO;CACV;AAID,MAAa,gBAAgB,OAAO,IAAI,UAAU;;;ACIlD,IAAa,UAAb,MAA4C;CACxC;CAEA;CAIA,YAAY,SAAyB;EACjC,KAAK,SAAS;EAEd,IAAI,OAAO,QAAQ,SAAS,UACxB,KAAK,OAAO,OAAO,iBAAiB,QAAQ,KAAK;EAGrD,KAAK,SAAS,KAAK,OAAO,SAAS,aAAa,KAAK,OAAO,OAAO,GAAG,KAAA;EAEtE,eAAe,MAAM,cAAc;;CAKvC,IAAI,OAAO;EACP,OAAO,KAAK,OAAO;;CAGvB,IAAI,OAAO;EACP,OAAO,KAAK,OAAO;;CAKvB,MAAM,SAAS,OAAwD;EACnE,IAAI;EAMJ,IAAI;EACJ,IAAI;EAEJ,IAAI;GAKA,MAAM,mBAAmB,KAAK,eAAe,MAAM,WAAW;GAI9D,IAAI;GAEJ,IAAI,kBAAkB;IAClB,MAAM,eAAe,MAAM;IAC3B,kBAAkB,IAAI,iBAAiB;IAEvC,IAAI,aAAa,SACb,gBAAgB,MAAM,aAAa,OAAO;SACvC;KACH,MAAM,gBAAgB,gBAAiB,MAAM,aAAa,OAAO;KACjE,aAAa,iBAAiB,SAAS,SAAS,EAAE,MAAM,MAAM,CAAC;KAC/D,8BAA8B,aAAa,oBAAoB,SAAS,QAAQ;;;GAOxF,eAAe,kBACX,MAAM,MAAM,gBAAgB,OAAO,GACnC,MAAM,OAAO;GAKjB,MAAM,SAAS,KAAK,OAAO,SAAS,YAAY,SAAS,CAAC,MAAM;GAEhE,IAAI,CAAC,UAAU,KAAK,OAAO,UACvB,MAAM,KAAK,OAAO,SAAS,aAAa;GAG5C,IAAI;GACJ,IAAI,QAAQ,QAEL,IAAI,KAAK,OAAO,SAAS,YAAY,OAAO;IAC/C,MAAM,EAAE,OAAO,KAAK;IACpB,aAAa,GAAG,MAAM,OAAQ,aAAa;UACxC;IACH,MAAM,EAAE,OAAO,KAAK;IACpB,aAAa,GAAG,aAAa;;GAGjC,IAAI;GACJ,IAAI,QAAQ,QAEL,IAAI,kBAEP,SAAS,MAAM,KAAK,yBACV,KAAK,qBAAqB,YAAY,aAAc,EAC1D,kBACA,gBACH;QACE,IAAI,UAAU,WAAW,EAAE;IAI9B,MAAM,UAAU,MAAM;IAEtB,SAAS,OAAO,YAAY,cACxB,MAAM,KAAK,qBAAqB,KAAA,GAAW,aAAa,GACxD;UACD,IAAI,OAAO,eAAe,aAG7B,SAAS,MAAM,KAAK,qBAAqB,KAAA,GAAW,aAAa;QAGjE,SAAS;GAKb,MAAM,SAAS,WAAW,QAAQ,aAAa;GAC/C,WAAW,UAAU,OAAO,GACxB,MAAM,SACN;GAEJ,IAAI,UAAU;IACV,MAAM,aAAa;IAGnB,IAAI,KAAK,OAAO,SAAS,YAAY,SAAS,MAAM,OAChD,MAAM,QAAQ,KAAA;;GAItB,IAAI,CAAC,UAAU,KAAK,OAAO,SACvB,MAAM,KAAK,OAAO,QAAQ,cAAc,SAAS;WAEhD,GAAG;GACR,MAAM,QAAQ,QAAQ,EAAE,GAAG,IAAI,YAAY,EAAE;GAM7C,IAAI,KAAK,OAAO,SACZ,IAAI;IACA,MAAM,KAAK,OAAO,QAAQ,MAAM,OAAO,gBAAgB,MAAM,OAAO,CAAC;YAChE,UAAU;IACf,MAAM,QAAQ,QAAQ,SAAS,GAAG,WAAW,YAAY,SAAS;;GAI1E,MAAM,MAAM;YACN;GACN,IAAI,uBACA,uBAAuB;;EAI/B,OAAO;;;;;;;;;;;;;CAgBX,MAAgB,qBACZ,YACA,cACgB;EAChB,MAAM,QAAQ,MAAM;EACpB,IAAI,OAAO,UAAU,aACjB,OAAO;EAGX,IAAI,aAAa,YACb,OAAO,aAAa;EAGxB,MAAM,EAAE,WAAW;EAEnB,IAAI,OAAO,SACP,MAAM,YAAY;GAAE,QAAQ;GAAK,SAAS;GAAmB,CAAC;EAGlE,OAAO,IAAI,SAAkB,SAAS,WAAW;GAC7C,MAAM,gBAAgB;IAClB,OAAO,oBAAoB,SAAS,QAAQ;IAC5C,OAAO,YAAY;KACf,QAAQ;KACR,SAAS;KACZ,CAAC,CAAC;;GAGP,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,MAAM,CAAC;GAEzD,aAAa,gBAAgB,CAAC,WAAW;IACrC,OAAO,oBAAoB,SAAS,QAAQ;IAC5C,QAAQ,aAAa,WAAW;KAClC;IACJ;;CAGN,MAAgB,mBACZ,IACA,kBACA,YACgB;EAChB,IAAI,CAAC,kBACD,OAAO,IAAI;EAGf,IAAI;EAEJ,IAAI;GACA,OAAO,MAAM,QAAQ,KAAK,CACtB,IAAI,EACJ,IAAI,SAAgB,GAAG,WAAW;IAC9B,UAAU,iBAAiB;KACvB,IAAI,YACA,WAAW,OAAO;KAEtB,OAAO,YAAY;MACf,QAAQ;MACR,SAAS;MACZ,CAAC,CAAC;OACJ,iBAAiB;KACtB,CACL,CAAC;YACI;GACN,aAAa,QAAQ;;;CAI7B,eAAyB,YAA4C;EACjE,MAAM,gBAAgB,WAAW;EACjC,MAAM,kBAAkB,KAAK,OAAO;EAEpC,IAAI,CAAC,iBAAiB,CAAC,iBACnB;EAGJ,IAAI,CAAC,eACD,OAAO;EAGX,IAAI,CAAC,iBACD,OAAO;EAGX,IAAI,WAAW,2BACX,OAAO;EAGX,OAAO,KAAK,IAAI,eAAe,gBAAgB;;;;;ACvPvD,SAAgB,kBAAkB,OAAsB;CACpD,IAAI,OAAO,UAAU,YACjB,OAAO,IAAI,QAAQ;EACf,MAAM,YAAY;EAClB,IAAI;EACP,CAAC;CAGN,OAAO,IAAI,QAAQ;EACf,MAAM,YAAY;EAClB,GAAG;EACN,CAAC;;;;AChBN,SAAgB,mBAAmB,OAAsB;CACrD,IAAI,OAAO,UAAU,YACjB,OAAO,IAAI,QAAQ;EACf,MAAM,YAAY;EAClB,IAAI;EACP,CAAC;CAGN,OAAO,IAAI,QAAQ;EACf,MAAM,YAAY;EAClB,GAAG;EACN,CAAC;;;;AC3BN,MAAM,WAA2B,uBAAO,UAAU;AAElD,SAAS,YACL,SACA,KACA,KAC+B;CAC/B,OAAO,IAAI,SAAS,SAAS,WAAW;EACpC,IAAI,UAAU;EAEd,MAAM,gBAAgB,OAAO,SAAS;EACtC,MAAM,iBAAiB,OAAO,SAAS;EACvC,MAAM,WAAW,UAAiB,KAAK,MAAM;EAE7C,SAAS,UAAU;GACf,IAAI,eAAe,SAAS,QAAQ;GACpC,IAAI,eAAe,UAAU,SAAS;GACtC,IAAI,eAAe,SAAS,QAAQ;;EAGxC,SAAS,OAAO,OAA+B;GAC3C,IAAI,SAAS;GACb,UAAU;GACV,SAAS;GACT,QAAQ,MAAM;;EAGlB,SAAS,KAAK,OAAgB;GAC1B,IAAI,SAAS;GACb,UAAU;GACV,SAAS;GACT,OAAO,MAAM;;EAGjB,IAAI,KAAK,SAAS,QAAQ;EAC1B,IAAI,KAAK,UAAU,SAAS;EAC5B,IAAI,KAAK,SAAS,QAAQ;EAE1B,IAAI;GACA,QAAQ,QAAQ,QAAQ,KAAK,IAAI,CAAC,CAC7B,WAAW,OAAO,SAAS,CAAC,CAC5B,MAAM,KAAK;WACX,OAAO;GACZ,KAAK,MAAM;;GAEjB;;AAGN,SAAS,eACL,SACA,KACA,KAC+B;CAC/B,OAAO,IAAI,SAAS,SAAS,WAAW;EACpC,IAAI,UAAU;EAEd,MAAM,gBAAgB,OAAO,SAAS;EACtC,MAAM,iBAAiB,OAAO,SAAS;EACvC,MAAM,WAAW,UAAiB,KAAK,MAAM;EAE7C,SAAS,UAAU;GACf,IAAI,eAAe,SAAS,QAAQ;GACpC,IAAI,eAAe,UAAU,SAAS;GACtC,IAAI,eAAe,SAAS,QAAQ;;EAGxC,SAAS,OAAO,OAA+B;GAC3C,IAAI,SAAS;GACb,UAAU;GACV,SAAS;GACT,QAAQ,MAAM;;EAGlB,SAAS,KAAK,OAAgB;GAC1B,IAAI,SAAS;GACb,UAAU;GACV,SAAS;GACT,OAAO,MAAM;;EAGjB,IAAI,KAAK,SAAS,QAAQ;EAC1B,IAAI,KAAK,UAAU,SAAS;EAC5B,IAAI,KAAK,SAAS,QAAQ;EAE1B,IAAI;GACA,QAAQ,QACJ,QAAQ,KAAK,MAAM,UAAU;IACzB,IAAI,OACA,KAAK,MAAM;SAEX,OAAO,IAAI,iBAAiB,IAAI,YAAY,WAAW,KAAA,EAAU;KAEvE,CACL,CAAC,MAAM,KAAK;WACR,OAAO;GACZ,KAAK,MAAM;;GAEjB;;AAGN,SAAS,iBAAiB,SAAuC,cAAgC;CAC7F,IAAI,OAAO,YAAY,YACnB,MAAM,IAAI,SAAS,yDAAyD;CAGhF,OAAO,kBAAkB,EACrB,KAAK,OAAO,UAAqB;EAC7B,MAAM,OAAO,MAAM,QAAQ,SAAS;EACpC,IAAI,CAAC,MAAM,OAAO,CAAC,MAAM,KACrB,MAAM,IAAI,SAAS,iEAAiE;EAGxF,MAAM,MAAM,KAAK;EACjB,MAAM,MAAM,KAAK;EAMjB,KAJe,eACX,MAAM,eAAe,SAA2B,KAAK,IAAI,GACzD,MAAM,YAAY,SAAwB,KAAK,IAAI,MAExC,UACX,OAAO;EAGX,OAAO,MAAM,MAAM;KAE1B,CAAC;;;;;;;;;;;;;;AAeN,SAAgB,gBAAgB,SAA+B;CAC3D,OAAO,iBAAiB,SAAS,MAAM;;;;;;;;;;;;;AAc3C,SAAgB,mBAAmB,SAAkC;CACjE,OAAO,iBAAiB,SAAS,KAAK;;;;ACjK1C,SAAgB,qBAAqB,OAA6C;CAC9E,OAAO,SAAS,MAAM,IAClB,OAAO,MAAM,UAAU;;AAG/B,SAAgB,aAAa,OAAqC;CAC9D,OAAO,OAAO,UAAU;;;;ACqB5B,SAAgB,eAAe,OAAsB;CACjD,IAAI,qBAAqB,MAAM,EAC3B,OAAO,eAAe,MAAM,MAAM,KAAK,MAAM,CAAC;CAGlD,IAAI,OAAO,UAAU,YACjB,MAAM,IAAI,SAAS,sEAAsE;CAG7F,OAAO,kBAAkB,EAAE,KAAK,UAAqB,MAAM,MAAM,QAAQ,EAAE,CAAC;;;;ACjChF,SAAgB,iBAAiB,OAA0C;CACvE,OAAO,SAAS,MAAM,IAClB,OAAO,MAAM,OAAO,cACpB,OAAO,MAAM,SAAS;;AAG9B,SAAgB,UAAU,OAAkC;CACxD,OAAO,cAAc,OAAO,cAAc;;;;;;;;;;;ACJ9C,SAAgB,mBACZ,eACA,eACO;CACP,OAAO,CAAC,iBACJ,kBAAkB,iBACjB,kBAAkB,WAAW,QAAQ,kBAAkB,WAAW;;;;ACX3E,SAAgB,mBAAmB,OAAkB,cAAuC;CACxF,MAAM,gBAAgB,MAAM,QAAQ,IAAI,WAAW,kBAAkB;CACrE,IAAI,CAAC,eACD,OAAO;CAGX,eAAe,OAAO,iBAAiB,WACnC,IAAI,KAAK,aAAa,GACtB;CAEJ,MAAM,YAAY,IAAI,KAAK,cAAc;CACzC,IAAI,OAAO,MAAM,UAAU,SAAS,CAAC,IAAI,OAAO,MAAM,aAAa,SAAS,CAAC,EACzE,OAAO;CAGX,OAAO,aAAa;;;;AChBxB,SAAgB,6BAA6B,OAA6B;CAGtE,OAFmB,qBAAqB,MAEvB,CAAC,UAAU;;AAGhC,SAAgB,4BAA4B,OAAkB,OAA+C;CACzG,QAAQ,SAAS,EAAE;CAEnB,MAAM,QAAQ,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM;CAEpD,IAAI,MAAM,WAAW,GACjB,OAAO,6BAA6B,MAAM,CAAC,OAAO;CAItD,OADmB,qBAAqB,MACvB,CAAC,SAAS,MAAM,CAAC,OAAO,IAAI,KAAA;;;;AChBjD,SAAgB,8BAA8B,OAA6B;CAEvE,OADmB,qBAAqB,MACvB,CAAC,WAAW;;AAGjC,SAAgB,6BAA6B,OAAkB,OAA+C;CAC1G,QAAQ,SAAS,EAAE;CAEnB,MAAM,QAAQ,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM;CAEpD,IAAI,MAAM,WAAW,GACjB,OAAO,8BAA8B,MAAM,CAAC,OAAO;CAIvD,OADmB,qBAAqB,MACvB,CAAC,UAAU,MAAM,CAAC,OAAO,IAAI,KAAA;;;;ACflD,SAAgB,8BAA8B,OAA6B;CAEvE,OADmB,qBAAqB,MACvB,CAAC,WAAW;;AAGjC,SAAgB,6BAA6B,OAAkB,OAAgD;CAC3G,QAAQ,SAAS,EAAE;CAEnB,MAAM,QAAQ,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM;CAEpD,IAAI,MAAM,WAAW,GACjB,OAAO,8BAA8B,MAAM,CAAC,OAAO;CAIvD,OADmB,qBAAqB,MACvB,CAAC,UAAU,MAAM,CAAC,OAAO,IAAI,KAAA;;;;ACblD,SAAgB,wBAAwB,OAAkB,aAA+B;CACrF,MAAM,SAAS,iBAAiB,OAAO,WAAW,aAAa;CAC/D,IAAI,CAAC,QACD,OAAO;CAGX,OAAO,OAAO,MAAM,IAAI,CAAC,GAAI,MAAM,KAAK,YAAY,YAAY;;;;ACFpE,SAAgB,mBAAmB,OAAkB,UAAkC,EAAE,EAAuB;CAC5G,IAAI;CACJ,IAAI,OAAO,QAAQ,eAAe,aAC9B,aAAa,kBAAkB,QAAQ,WAAW;MAElD,aAAa,MAAM,WAAW,cAAc;CAGhD,IAAI,WAAW,MAAM,QAAQ,IAAI,WAAW,iBAAiB;CAC7D,IAAI,CAAC,YAAY,CAAC,MAAM,QAAQ,MAAM,CAAC,WAAW,MAAM,QAAQ,IAAI,EAAE,EAClE,WAAW,MAAM,QAAQ,IAAI,WAAW,KAAK;MAC1C,IAAI,YAAY,SAAS,SAAS,IAAI,EACzC,WAAW,SAAS,UAAU,GAAG,SAAS,QAAQ,IAAI,CAAC,CAAC,SAAS;CAGrE,IAAI,CAAC,UACD;CAIJ,MAAM,SAAS,SAAS,OAAO,MAC3B,SAAS,QAAQ,IAAI,GAAG,IACxB;CACJ,MAAM,QAAQ,SAAS,QAAQ,KAAK,OAAO;CAE3C,MAAM,SAAS,UAAU,KACrB,SAAS,UAAU,GAAG,MAAM,GAC5B;CAIJ,IAAI,wBAAwB,KAAK,OAAO,EACpC;CAGJ,OAAO;;;;;;;;;;;AC5BX,SAAgB,aAAa,OAAkB,UAA4B,EAAE,EAAuB;CAChG,IAAI;CACJ,IAAI,OAAO,QAAQ,eAAe,aAC9B,aAAa,kBAAkB,QAAQ,WAAW;MAElD,aAAa,MAAM,WAAW,cAAc;CAGhD,MAAM,aAAa,MAAM,QAAQ;CACjC,IAAI,CAAC,YACD;CAIJ,MAAM,YAAY,MAAM,QAAQ,IAAI,WAAW,gBAAgB;CAC/D,MAAM,QAAkB,CAAC,WAAW;CAEpC,IAAI,WAAW;EACX,MAAM,QAAQ,UAAU,MAAM,IAAI;EAClC,KAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK;GACxC,MAAM,OAAO,MAAM,GAAI,MAAM;GAC7B,IAAI,MACA,MAAM,KAAK,KAAK;;;CAO5B,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,SAAS,GAAG,KAClC,IAAI,CAAC,WAAW,MAAM,IAAK,EAAE,EACzB,OAAO,MAAM;CAKrB,OAAO,MAAM,MAAM,SAAS;;;;AC1ChC,SAAgB,mBACZ,OACA,UAAkC,EAAE,EAC7B;CACP,IAAI;CACJ,IAAI,OAAO,QAAQ,eAAe,aAC9B,aAAa,kBAAkB,QAAQ,WAAW;MAElD,aAAa,MAAM,WAAW,cAAc;CAIhD,IAAI;CACJ,IAAI;EAEA,IAAI,IADY,IAAI,MAAM,QAAQ,IAC3B,CAAC,aAAa,UACjB,WAAW;OAEX,WAAW;SAEX;EACJ,WAAW,QAAQ,WAAW;;CAGlC,IAAI,CAAC,MAAM,QAAQ,MAAM,CAAC,WAAW,MAAM,QAAQ,IAAI,EAAE,EACrD,OAAO;CAGX,MAAM,SAAS,MAAM,QAAQ,IAAI,WAAW,kBAAkB;CAC9D,IAAI,CAAC,QACD,OAAO;CAGX,MAAM,QAAQ,OAAO,QAAQ,IAAI;CAEjC,MAAM,YAAY,UAAU,KACxB,OAAO,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,GAC/C,OAAO,MAAM,CAAC,aAAa;CAE/B,IAAI,cAAc,UAAU,cAAc,SACtC,OAAO;CAGX,OAAO;;;;AC5CX,SAAS,YAAY,KAAc;;CAE/B,IAAI,OAAO,QAAQ,YAAY,IAAI,WAAW,GAC1C,OAAO;CAGX,IAAI;EACA,OAAO,mBAAmB,IAAI;SAC1B;EACJ,OAAO;;;AAIf,IAAa,cAAb,MAAiD;CAC7C;CAEA;CAEA,aAA+B,EAAE;CAEjC;CAEA,YAAY,MAAY,SAA8B;EAClD,KAAK,OAAO;EAEZ,KAAK,gBAAgB,WAAW,EAAE;EAClC,MAAM,SAAS,aAAa,MAAM,QAAQ;EAE1C,KAAK,SAAS,OAAO;EACrB,KAAK,aAAa,OAAO;;CAG7B,KAAK,MAAwB;EACzB,OAAO,KAAK,OAAO,KAAK,KAAK;;CAGjC,KAAK,MAAkD;EACnD,IACI,KAAK,SAAS,OACd,KAAK,cAAc,QAAQ,OAE3B,OAAO;GACH,MAAM;GACN,QAAQ,OAAO,OAAO,KAAK;GAC9B;EAGL,MAAM,QAAQ,KAAK,OAAO,KAAK,KAAK;EAEpC,IAAI,CAAC,OACD;EAGJ,MAAM,SAAmC,OAAO,OAAO,KAAK;EAE5D,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;GACnC,MAAM,MAAM,KAAK,WAAW,IAAI;GAChC,IAAI,CAAC,KAAK;GACV,MAAM,OAAO,IAAI;GACjB,MAAM,MAAM,YAAY,MAAM,GAAG;GAEjC,IAAI,OAAO,QAAQ,aACf,OAAO,QAAQ;;EAIvB,OAAO;GACH,MAAM,MAAM;GACZ;GACH;;;;;AC5ET,SAAgB,OAAO,OAA+B;CAClD,OAAO,OAAO,UAAU;;;;ACH5B,MAAa,kBAAkB;CAC3B,QAAQ;CACR,eAAe;CACf,SAAS;CACZ;;;ACAD,MAAM,qBAAqB,IAAI,IAAY,OAAO,OAAO,gBAAgB,CAAC;AAE1E,SAAgB,cAAc,OAAsC;CAChE,IAAI,CAAC,QAAQ,MAAM,EACf,OAAO;CAGX,OAAO,mBAAmB,IAAI,MAAM,KAAK;;;;ACP7C,IAAa,cAAb,cAAiC,SAAS;CACtC,YAAY,QAAwB,EAAE,EAAE;EACpC,MAAM,UAAU,OAAO,UAAU,WAAW,EAAE,SAAS,OAAO,GAAG,EAAE,GAAI,OAAkB;EACzF,IAAI,EAAE,UAAU,YAAY,CAAE,QAAoC,MAC9D,QAAqC,OAAO,gBAAgB;EAEhE,MAAM,QAA0B;EAChC,KAAK,OAAO;;;;;ACRpB,IAAa,qBAAb,cAAwC,YAAY;CAChD;CAEA,YAAY,YAAoB,OAAe;EAC3C,MAAM;GACF,SAAS,6BAA6B,WAAW;GACjD,MAAM,gBAAgB;GACtB;GACH,CAAC;EACF,KAAK,OAAO;EACZ,KAAK,aAAa;;;;;ACV1B,IAAa,0BAAb,cAA6C,YAAY;CACrD;CAEA;CAEA,YAAY,YAAoB,YAAoB;EAChD,MAAM;GACF,SAAS,GAAG,WAAW,mBAAmB,WAAW,yCACjB,WAAW;GAC/C,MAAM,gBAAgB;GACzB,CAAC;EACF,KAAK,OAAO;EACZ,KAAK,aAAa;EAClB,KAAK,aAAa;;;;;ACb1B,SAAgB,SAAS,OAAiC;CACtD,IAAI,CAAC,SAAS,MAAM,EAChB,OAAO;CAGX,IACI,OAAO,MAAM,SAAS,eACtB,OAAO,MAAM,SAAS,UAEtB,OAAO;CAGX,OAAO,OAAO,MAAM,YAAY,cAC5B,MAAM,QAAQ,WAAW;;;;;;;;;;;;;;;;;;;;;ACKjC,SAAgB,sBACZ,OACwB;CACxB,IAAI,OAAO,MAAM,SAAS,aACtB;CAGJ,MAAM,MAAM,OAAO,MAAM,WAAW;CAKpC,IAAI,CAAC,OAAO,MAAM,SAAS,KACvB;CAGJ,OAAO,IAAI,YAAY,MAAM,MAAM,EAAE,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;ACb/C,IAAa,eAAb,MAAyF;CACrF;CAEA;CAEA;CAEA,YAAY,UAAgC,EAAE,EAAE;EAC5C,KAAK,UAAU,EAAE;EACjB,KAAK,YAAY,EAAE;EACnB,KAAK,QAAQ,QAAQ;;CAGzB,IAAI,OAAuB;EACvB,KAAK,QAAQ,KAAK,MAAM;EACxB,KAAK,UAAU,KAAK,sBAAsB,MAAM,CAAC;EAIjD,KAAK,OAAO,OAAO;;CAGvB,OAAO,MAAc,SAAoD;EAMrE,MAAM,SAAS,KAAK,OAAO,IAAI,KAAK;EACpC,IAAI,OAAO,WAAW,aAClB,OAAO;EAGX,MAAM,UAA2B,EAAE;EAEnC,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,QAAQ,KAAK;GAC1C,MAAM,QAAQ,KAAK,QAAQ;GAC3B,MAAM,UAAU,KAAK,UAAU;GAE/B,IAAI,SAAS;IACT,MAAM,SAAS,QAAQ,KAAK,KAAK;IACjC,IAAI,OAAO,WAAW,aAClB;IAEJ,QAAQ,KAAK;KACT;KACA,OAAO;KACP,QAAQ,OAAO;KACf,MAAM,OAAO;KAChB,CAAC;IACF;;GAKJ,QAAQ,KAAK;IACT;IACA,OAAO;IAIP,QAAQ,OAAO,OAAO,KAAK;IAC9B,CAAC;;EAGN,KAAK,OAAO,IAAI,MAAM,QAAQ;EAC9B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC3Df,MAAM,eAAe;AAErB,MAAM,aAAa;;;;;;;;;AAsBnB,SAAS,gBAAgB,SAA+B;CACpD,IAAI,YAAY,IACZ,OAAO;CAGX,IAAI,YAAY,KACZ,OAAO;EAAE,MAAM;EAAS,MAAM;EAAK;CAGvC,IAAI,QAAQ,OAAO,EAAE,KAAK,KAAK;EAC3B,MAAM,OAAO,QAAQ,MAAM,EAAE;EAC7B,IAAI,WAAW,KAAK,KAAK,EACrB,OAAO;GAAE,MAAM;GAAS,MAAM;GAAM;EAExC,OAAO;;CAGX,IAAI,QAAQ,OAAO,EAAE,KAAK,KAAK;EAC3B,MAAM,WAAW,QAAQ,OAAO,QAAQ,SAAS,EAAE,KAAK;EACxD,MAAM,UAAU,WAAW,QAAQ,MAAM,GAAG,GAAG,GAAG,QAAQ,MAAM,EAAE;EAClE,IAAI,WAAW,KAAK,QAAQ,EACxB,OAAO;GACH,MAAM;GACN,MAAM;GACN;GACH;EAEL,OAAO;;CAKX,IAAI,uBAAuB,KAAK,QAAQ,EACpC,OAAO;EAAE,MAAM;EAAW,OAAO;EAAS;CAG9C,OAAO;;;;;;;;;;;AAYX,SAAS,aAAa,MAA8B;CAChD,MAAM,UAAU,KAAK,OAAO,EAAE,KAAK,MAAM,KAAK,MAAM,EAAE,GAAG;CACzD,IAAI,YAAY,IACZ,OAAO,EAAE;CAGb,MAAM,SAAkB,EAAE;CAC1B,IAAI,IAAI;CACR,MAAM,IAAI,QAAQ;CAElB,OAAO,IAAI,GAAG;EACV,IAAI,QAAQ,OAAO,EAAE,KAAK,KAAK;GAG3B,IAAI,QAAQ;GACZ,KAAK,IAAI,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;IAC5B,MAAM,IAAI,QAAQ,OAAO,EAAE;IAC3B,IAAI,MAAM,KACN,OAAO;IAEX,IAAI,MAAM,KAAK;KACX,QAAQ;KACR;;;GAGR,IAAI,UAAU,IACV,OAAO;GAEX,MAAM,QAAQ,QAAQ,MAAM,IAAI,GAAG,MAAM;GAGzC,IAAI,MAAM,OAAO,EAAE,KAAK,KACpB,OAAO;GAOX,MAAM,QAAQ,QAAQ,IAAI,IAAI,QAAQ,OAAO,QAAQ,EAAE,GAAG;GAC1D,IAAI,UAAU,MAAM,UAAU,OAAO,UAAU,KAC3C,OAAO;GAEX,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;GAClC,MAAM,cAAc,aAAa,MAAM;GACvC,IAAI,gBAAgB,MAChB,OAAO;GAEX,KAAK,MAAM,KAAK,aACZ,OAAO,KAAK,EAAE;GAElB,OAAO,KAAK,EAAE,MAAM,cAAc,CAAC;GACnC,IAAI,QAAQ;GACZ;;EAIJ,IAAI,SAAS;EACb,OAAO,SAAS,GAAG;GACf,MAAM,IAAI,QAAQ,OAAO,OAAO;GAChC,IAAI,MAAM,OAAO,MAAM,KACnB;GAEJ;;EAEJ,MAAM,UAAU,QAAQ,MAAM,GAAG,OAAO;EACxC,IAAI,YAAY,IAAI;GAChB,MAAM,QAAQ,gBAAgB,QAAQ;GACtC,IAAI,UAAU,MACV,OAAO;GAEX,OAAO,KAAK,MAAM;;EAEtB,IAAI;EACJ,IAAI,IAAI,KAAK,QAAQ,OAAO,EAAE,KAAK,KAC/B;;CAIR,OAAO;;;;;;;;;;;;;;;;;;AAmBX,SAAS,OAAO,QAAmC;CAC/C,IAAI,WAAsB,CAAC,EAAE,CAAC;CAE9B,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;EACpC,MAAM,QAAQ,OAAO;EAErB,IAAI,MAAM,SAAS,aAAa;GAG5B,IAAI,QAAQ;GACZ,IAAI,QAAQ;GACZ,KAAK,IAAI,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;IACxC,MAAM,IAAI,OAAO;IACjB,IAAI,EAAE,SAAS,aAAa;SACvB,IAAI,EAAE,SAAS,cAAc;KAC9B;KACA,IAAI,UAAU,GAAG;MACb,QAAQ;MACR;;;;GAIZ,IAAI,UAAU,IACV,OAAO;GAGX,MAAM,gBAAgB,OADR,OAAO,MAAM,IAAI,GAAG,MACA,CAAC;GACnC,IAAI,kBAAkB,MAClB,OAAO;GAKX,MAAM,OAAkB,EAAE;GAC1B,KAAK,MAAM,KAAK,UAAU;IACtB,IAAI,KAAK,UAAU,cACf,OAAO;IAEX,KAAK,KAAK,EAAE,OAAO,CAAC;IACpB,KAAK,MAAM,gBAAgB,eAAe;KACtC,IAAI,KAAK,UAAU,cACf,OAAO;KAEX,KAAK,KAAK,EAAE,OAAO,aAAa,CAAC;;;GAGzC,WAAW;GACX,IAAI;GACJ;;EAGJ,IAAI,MAAM,SAAS,WAAW,MAAM,UAAU;GAC1C,MAAM,WAAkB;IACpB,MAAM;IACN,MAAM,MAAM;IACZ,UAAU;IACb;GACD,MAAM,OAAkB,EAAE;GAC1B,KAAK,MAAM,KAAK,UAAU;IACtB,IAAI,KAAK,UAAU,cACf,OAAO;IAEX,KAAK,KAAK,EAAE,OAAO,CAAC;IACpB,IAAI,KAAK,UAAU,cACf,OAAO;IAEX,KAAK,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;;GAEnC,WAAW;GACX;;EAGJ,KAAK,MAAM,KAAK,UACZ,EAAE,KAAK,MAAM;;CAIrB,OAAO;;AAGX,SAAS,eAAe,GAA0B;CAC9C,IAAI,EAAE,SAAS,WAAW,OAAO;EAAE,MAAM;EAAU,OAAO,EAAE;EAAO;CACnE,IAAI,EAAE,SAAS,SAAS,OAAO;EAAE,MAAM;EAAS,MAAM,EAAE;EAAM;CAC9D,IAAI,EAAE,SAAS,SAAS,OAAO;EAAE,MAAM;EAAS,MAAM,EAAE;EAAM;CAG9D,OAAO;;;;;;;;AASX,SAAS,WAAW,MAAyB;CACzC,IAAI,MAAM;CACV,KAAK,MAAM,KAAK,MACZ,IAAI,EAAE,SAAS,UAAU,OAAO,MAAM,EAAE;MACnC,IAAI,EAAE,SAAS,SAAS,OAAO,MAAM,EAAE;MACvC,OAAO,MAAM,EAAE;CAExB,OAAO;;AAGX,SAAgB,UAAU,MAAkC;CACxD,MAAM,SAAS,aAAa,KAAK;CACjC,IAAI,WAAW,MACX,OAAO;CAEX,MAAM,WAAW,OAAO,OAAO;CAC/B,IAAI,aAAa,MACb,OAAO;CAGX,MAAM,SAAsB,EAAE;CAC9B,MAAM,uBAAO,IAAI,KAAa;CAE9B,KAAK,MAAM,KAAK,UAAU;EACtB,MAAM,OAAkB,EAAE;EAC1B,KAAK,MAAM,KAAK,GAAG;GACf,MAAM,IAAI,eAAe,EAAE;GAC3B,IAAI,MAAM,MACN,OAAO;GAEX,KAAK,KAAK,EAAE;;EAShB,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,SAAS,GAAG,KACjC,IAAI,KAAK,GAAI,SAAS,SAClB,OAAO;EAIf,MAAM,MAAM,WAAW,KAAK;EAC5B,IAAI,KAAK,IAAI,IAAI,EACb;EAEJ,KAAK,IAAI,IAAI;EACb,OAAO,KAAK,KAAK;;CAErB,OAAO;;;;ACzVX,SAAgB,sBAAiF;CAC7F,OAAO,OAAO,OAAO,KAAK;;AAG9B,SAAgB,iBAAuE;CACnF,OAAO;EACH,gCAAgB,IAAI,KAAK;EACzB,aAAa,qBAAwB;EACrC,aAAa,qBAAwB;EACrC,cAAc,EAAE;EACnB;;;;ACIL,SAAS,YAAY,GAAmB;CACpC,IAAI;EACA,OAAO,mBAAmB,EAAE;SACxB;EACJ,OAAO;;;;;;;;;;AAWf,SAAS,kBACL,UACA,UACkC;CAClC,MAAM,MAAM,OAAO,OAAO,KAAK;CAC/B,KAAK,MAAM,OAAO,UACd,IAAI,IAAI,SAAS,WACb,IAAI,IAAI,QAAQ,YAAY,SAAS,IAAI,OAAQ;MAC9C;EAEH,MAAM,QAAQ,SAAS,MAAM,IAAI,MAAM,CAAC,KAAK,IAAI;EACjD,IAAI,IAAI,QAAQ,YAAY,MAAM;;CAG1C,OAAO;;;;;;;;;;;;;;;AAgBX,SAAS,gBACL,UACA,YACA,iBACM;CACN,MAAM,OAAO,kBAAkB,SAAS,SAAS;CACjD,IAAI,SAAS,GACT,OAAO;CAEX,OAAO,IAAI,SAAS,MAAM,GAAG,KAAK,CAAC,KAAK,IAAI;;;;;;;;AAShD,SAAS,oBAAoB,UAAqC;CAC9D,MAAM,MAAsB,EAAE;CAC9B,KAAK,MAAM,CAAC,GAAG,QAAQ,SAAS,SAAS,EACrC,IAAI,IAAI,SAAS,SACb,IAAI,KAAK;EACL,MAAM;EACN,OAAO;EACP,MAAM,IAAI;EACb,CAAC;MACC,IAAI,IAAI,SAAS,SAAS;EAC7B,IAAI,KAAK;GACL,MAAM;GACN,OAAO;GACP,MAAM,IAAI;GACb,CAAC;EAGF;;CAGR,OAAO;;;;;;;;;;;AAYX,SAAS,iBAAiB,QAA8D;CACpF,IAAI,OAAO,WAAW,eAAe,WAAW,WAAW,SACvD,OAAO;CAEX,IAAI,WAAW,WAAW,MACtB,OAAO;EAAC;EAAI,WAAW;EAAM,WAAW;EAAI;CAEhD,OAAO,CAAC,IAAI,OAAO;;AAGvB,SAAS,WACL,SACA,QACA,KACI;CACJ,MAAM,OAAO,iBAAiB,OAAO;CACrC,IAAI,SAAS,MAAM;EACf,KAAK,MAAM,KAAK,SAAS;GACrB,MAAM,OAAO,QAAQ;GACrB,KAAK,MAAM,KAAK,MAAM,IAAI,KAAK,EAAE;;EAErC;;CAEJ,KAAK,MAAM,KAAK,MAAM;EAClB,MAAM,OAAO,QAAQ;EACrB,IAAI,CAAC,MAAM;EACX,KAAK,MAAM,KAAK,MAAM,IAAI,KAAK,EAAE;;;AAIzC,SAAS,aAAsC,SAAoC;CAE/E,KAAK,MAAM,MAAM,SACb,OAAO;CAEX,OAAO;;AAGX,SAAS,eACL,SACA,WACA,OACI;CACJ,MAAM,SAAS,QAAQ;CACvB,IAAI,QACA,OAAO,KAAK,MAAM;MAElB,QAAQ,aAAa,CAAC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CpC,IAAa,aAAb,MAAuF;;;;;;;;CAQnF;CAEA;;;;;;;CAQA;CAEA;CAEA,YAAY,UAAgC,EAAE,EAAE;EAC5C,KAAK,cAAc;EACnB,KAAK,OAAO,gBAAmB;EAC/B,KAAK,YAAY,EAAE;EACnB,KAAK,QAAQ,QAAQ;;CAGzB,IAAI,OAAuB;EACvB,MAAM,QAAQ,KAAK;EAYnB,IAAI,OAAO,MAAM,SAAS,YAAY,MAAM,SAAS,MAAM,MAAM,SAAS,KAAK;GAC3E,KAAK,UAAU,KAAK;IAChB;IACA;IACA,SAAS,sBAAsB,MAAM;IACxC,CAAC;GACF,KAAK,OAAO,OAAO;GACnB;;EAGJ,MAAM,WAAW,UAAU,MAAM,KAAK;EACtC,IAAI,aAAa,MAAM;GAInB,KAAK,UAAU,KAAK;IAChB;IACA;IACA,SAAS,sBAAsB,MAAM;IACxC,CAAC;GACF,KAAK,OAAO,OAAO;GACnB;;EAMJ,KAAK,MAAM,YAAY,UACnB,KAAK,eAAe,UAAU,OAAO,MAAM;EAE/C,KAAK,OAAO,OAAO;;CAGvB,OAAO,MAAc,QAAmD;EAIpE,MAAM,WAAW,GAAG,UAAU,GAAG,IAAI;EACrC,MAAM,SAAS,KAAK,OAAO,IAAI,SAAS;EACxC,IAAI,OAAO,WAAW,aAClB,OAAO;EAGX,MAAM,aAAgC,EAAE;EAExC,KAAK,MAAM,KAAK,KAAK,WACjB,WAAW,KAAK,EAAE;EAGtB,MAAM,WAAW,KAAK,iBAAiB,KAAK;EAC5C,MAAM,eAAe,KAAK,aAAa,UAAU,OAAO;EACxD,IAAI,iBAAiB,MACjB,KAAK,MAAM,KAAK,cACZ,WAAW,KAAK,EAAE;OAGtB,KAAK,KAAK,KAAK,MAAM,UAAU,GAAG,YAAY,OAAO;EAczD,WAAW,MAAM,GAAG,MAAM;GACtB,IAAI,EAAE,UAAU,EAAE,OAAO,OAAO,EAAE,QAAQ,EAAE;GAC5C,MAAM,KAAK,EAAE,cAAc;GAE3B,QADW,EAAE,cAAc,MACf;IACd;EAEF,MAAM,UAA2B,EAAE;EACnC,IAAI,YAAY;EAChB,KAAK,MAAM,aAAa,YAAY;GAChC,MAAM,EACF,OACA,OACA,SACA,gBACA,eACA;GAEJ,IAAI,UAAU,WACV;GAGJ,IAAI,SAAS;IAET,MAAM,SAAS,QAAQ,KAAK,KAAK;IACjC,IAAI,OAAO,WAAW,aAClB;IAEJ,QAAQ,KAAK;KACT;KACA;KACA,QAAQ,KAAK,aAAa,OAAO,OAAO;KACxC,MAAM,OAAO;KAChB,CAAC;IACF,YAAY;IACZ;;GAGJ,IAAI,kBAAkB,OAAO,eAAe,UAAU;IAGlD,QAAQ,KAAK;KACT;KACA;KACA,QAAQ,kBAAkB,UAAU,eAAe;KACnD,MAAM,gBAAgB,UAAU,YAAY,UAAU,oBAAoB,KAAK;KAClF,CAAC;IACF,YAAY;IACZ;;GAIJ,QAAQ,KAAK;IACT;IACA;IACA,QAAQ,OAAO,OAAO,KAAK;IAC9B,CAAC;GACF,YAAY;;EAGhB,KAAK,OAAO,IAAI,UAAU,QAAQ;EAClC,OAAO;;;;;;;;;;;;CAaX,aAAuB,UAAoB,QAA8D;EACrG,IAAI,OAAO,KAAK;EAEhB,KAAK,MAAM,WAAW,UAAU;GAK5B,IAAI,KAAK,cAAc,aAAa,KAAK,YAAY,IAAI,KAAK,aAAa,SAAS,GAChF,OAAO;GAGX,MAAM,QAAQ,KAAK,eAAe,IAAI,QAAS;GAC/C,IAAI,CAAC,OACD,OAAO;GAEX,OAAO;;EAGX,IAAI,KAAK,cAAc,aAAa,KAAK,YAAY,IAAI,KAAK,aAAa,SAAS,GAChF,OAAO;EAKX,MAAM,MAAyB,EAAE;EACjC,WAAW,KAAK,aAAa,QAAQ,IAAI;EACzC,OAAO;;CAGX,iBAA2B,MAAwB;EAC/C,MAAM,UAAU,KAAK,OAAO,EAAE,KAAK,MAAM,KAAK,MAAM,EAAE,GAAG;EACzD,IAAI,YAAY,IACZ,OAAO,EAAE;EAEb,MAAM,QAAQ,QAAQ,MAAM,IAAI;EAChC,MAAM,SAAmB,EAAE;EAC3B,KAAK,MAAM,QAAQ,OACf,IAAI,SAAS,IACT,OAAO,KAAK,KAAK;EAGzB,OAAO;;CAGX,eAAyB,UAAqB,OAAiB,OAAqB;EAChF,IAAI,OAAO,KAAK;EAChB,MAAM,QAAQ,KAAK,kBAAkB,MAAM;EAC3C,MAAM,YAAY,MAAM,UAAU;EAClC,MAAM,iBAAiB,oBAAoB,SAAS;EAEpD,KAAK,MAAM,CAAC,GAAG,YAAY,SAAS,SAAS,EAAE;GAC3C,MAAM,MAAM;GAEZ,IAAI,IAAI,SAAS,SAAS;IAOtB,eAAe,KAAK,aAAa,WAAW;KACxC;KACA;KACA;KACA,YAAY;KACZ,iBAAiB;KACpB,CAAC;IACF;;GAGJ,IAAI,IAAI,SAAS,SAAS;IACtB,IAAI,CAAC,KAAK,YACN,KAAK,aAAa,gBAAgB;IAEtC,OAAO,KAAK;IACZ;;GAGJ,IAAI,QAAQ,KAAK,eAAe,IAAI,IAAI,MAAM;GAC9C,IAAI,CAAC,OAAO;IACR,QAAQ,gBAAgB;IACxB,KAAK,eAAe,IAAI,IAAI,OAAO,MAAM;;GAE7C,OAAO;;EAGX,MAAM,UAA2B;GAC7B;GACA;GACA;GACA,YAAY,SAAS;GACxB;EAED,IAAI,OACA,eAAe,KAAK,aAAa,WAAW,QAAQ;OAIpD,KAAK,aAAa,KAAK,QAAQ;;CAIvC,KACI,MACA,UACA,OACA,WACA,QACI;EAEJ,WAAW,KAAK,aAAa,QAAQ,UAAU;EAE/C,IAAI,UAAU,SAAS,QAAQ;GAG3B,WAAW,KAAK,aAAa,QAAQ,UAAU;GAC/C,KAAK,MAAM,KAAK,KAAK,cACjB,UAAU,KAAK,EAAE;GAErB;;EAKJ,KAAK,MAAM,KAAK,KAAK,cACjB,UAAU,KAAK,EAAE;EAGrB,MAAM,MAAM,SAAS;EAErB,MAAM,cAAc,KAAK,eAAe,IAAI,IAAI;EAChD,IAAI,aACA,KAAK,KAAK,aAAa,UAAU,QAAQ,GAAG,WAAW,OAAO;EAGlE,IAAI,KAAK,YACL,KAAK,KAAK,KAAK,YAAY,UAAU,QAAQ,GAAG,WAAW,OAAO;;CAI1E,kBAA4B,OAA0B;EAClD,OAAO,OAAO,MAAM,WAAW;;;;;;;CAQnC,aACI,QACkC;EAClC,MAAM,MAAM,OAAO,OAAO,KAAK;EAC/B,KAAK,MAAM,KAAK,QACZ,IAAI,OAAO,UAAU,eAAe,KAAK,QAAQ,EAAE,EAC/C,IAAI,KAAK,OAAO;EAGxB,OAAO;;;;;;;;;;;;ACrhBf,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;AA4B1B,IAAa,cAAb,MAAwF;CACpF;CAEA,UAAgC,EAAE;CAElC;;;;;CAMA;CAEA,YAAY,UAAiC,EAAE,EAAE;EAC7C,KAAK,YAAY,QAAQ,aAAa;EACtC,KAAK,QAAQ,QAAQ;;CAGzB,IAAI,OAAuB;EACvB,IAAI,KAAK,OAAO;GACZ,KAAK,MAAM,IAAI,MAAM;GACrB;;EAEJ,KAAK,QAAQ,KAAK,MAAM;;CAG5B,OAAO,MAAc,QAA2C;EAC5D,IAAI,CAAC,KAAK,OAAO;GACb,KAAK,QAAQ,KAAK,QAAQ;GAC1B,KAAK,MAAM,KAAK,KAAK,SACjB,KAAK,MAAM,IAAI,EAAE;GAErB,KAAK,UAAU,EAAE;;EAErB,OAAO,KAAK,MAAM,OAAO,MAAM,OAAO;;;;;;;;;CAU1C,SAA+B;EAC3B,IAAI,KAAK,QAAQ,SAAS,KAAK,WAC3B,OAAO,IAAI,aAAgB,EAAE,OAAO,KAAK,OAAO,CAAC;EAErD,OAAO,IAAI,WAAc,EAAE,OAAO,KAAK,OAAO,CAAC;;;;;ACjFvD,SAAgB,oBAAoB,OAAoC;CACpE,IAAI;CACJ,IAAI,OAAO,MAAM,SAAS,aAMtB,IAAI,MAAM,SAAS,QAAQ,MAAM,SAAS,OACtC,OAAO;MAEP,OAAO,YAAY,MAAM,KAAK;CAItC,IAAI;CACJ,IAAI,OAAO,MAAM,eAAe,aAC5B,aAAa,kBAAkB,MAAM,WAAW;CAGpD,IAAI,OAAO,MAAM,YAAY;MAErB,CAAC,OAAO,SAAS,MAAM,QAAQ,IAC/B,MAAM,WAAW,GAEjB,OAAO,MAAM;;CAIrB,IAAI,OAAO,MAAM,mBAAmB;MAE5B,CAAC,OAAO,SAAS,MAAM,eAAe,IACtC,MAAM,kBAAkB,GAExB,OAAO,MAAM;;CAIrB,OAAO;EACH,GAAG;EACH;EACA;EACH;;;;AClDL,MAAa,YAAY,OAAO,IAAI,MAAM;;;;;;;;;;;;;;;;;;;ACqB1C,SAAgB,cAAc,OAA+B;CACzD,IAAI,cAAc,OAAO,UAAU,EAC/B,OAAO;CAEX,IAAI,CAAC,SAAS,MAAM,EAChB,OAAO;CAEX,OAAO,OAAO,MAAM,UAAU,cAC1B,MAAM,QAAQ,MAAM,OAAO,IAC3B,SAAS,MAAM,QAAQ,IACvB,SAAS,MAAM,iBAAiB;;;;;;;;;;ACUxC,SAAS,iBACL,OACA,aACI;CAEJ,IAAI,UAAU;CAEd,KAAK,MAAM,MAAM,aAAa;EAC1B,UAAU;EACV;;CAEJ,IAAI,CAAC,SACD;CAEJ,MAAM,SAAS;EACX,GAAG,MAAM;EACT,GAAG;EACN;;AAGL,IAAa,MAAb,MAAa,IAAoB;;;;CAI7B;;;;;;;CAQA;;;;;;;;;CAUA;;;;;;;;CASA;;;;;;;;;;;;;;;;;;;CAoBA;;;;;;;;;;CAWA;;;;;;;CAQA,UAAsC,EAAE;CAIxC,YAAY,QAAoB,EAAE,EAAE;EAChC,KAAK,OAAO,MAAM;EAClB,KAAK,QAAQ,MAAM;EAEnB,KAAK,2BAAW,IAAI,KAAK;EACzB,KAAK,oCAAoB,IAAI,KAAK;EAClC,KAAK,SAAS,MAAM,UAAU,IAAI,cAAuB;EAEzD,KAAK,WAAW,OAAO,OAAO,oBAAoB,MAAM,WAAW,EAAE,CAAC,CAAC;EAKvE,eAAe,MAAM,UAAU;;;;;;;CAUnC,IAAI,SAAoC;EACpC,OAAO,KAAK;;;;;;;;;;;;;CAchB,IAAI,UAAwE;EACxE,OAAO,KAAK;;;;;;;;;;CAWhB,IAAI,mBAAwC;EACxC,OAAO,KAAK;;;;;;;;;CAUhB,SAAmB,OAA6B;EAC5C,KAAK,OAAO,IAAI,MAAM;EACtB,KAAK,QAAQ,KAAK,MAAM;;;;;;;;;;;CAY5B,UAAU,QAAgC;EACtC,KAAK,MAAM,SAAS,KAAK,SACrB,OAAO,IAAI,MAAM;EAErB,KAAK,SAAS;;;;;;CASlB,MAAM,MAAM,SAAwC;EAChD,MAAM,QAAQ,IAAI,gBAAgB,QAAQ;EAE1C,IAAI;EAEJ,IAAI;GACA,MAAM,YAAY,KAAK,SAAS;GAEhC,IAAI,WAAW;IACX,MAAM,aAAa,IAAI,iBAAiB;IACxC,MAAM,SAAS,WAAW;IAE1B,IAAI;IAEJ,IAAI;KACA,WAAW,MAAM,QAAQ,KAAK,CAC1B,KAAK,SAAS,MAAM,EACpB,IAAI,SAAgB,GAAG,WAAW;MAC9B,UAAU,iBAAiB;OACvB,WAAW,OAAO;OAClB,OAAO,YAAY;QACf,QAAQ;QACR,SAAS;QACZ,CAAC,CAAC;SACJ,UAAU;OACf,CACL,CAAC;cACI;KACN,aAAa,QAAQ;;UAGzB,WAAW,MAAM,KAAK,SAAS,MAAM;WAEpC,GAAG;GACR,MAAM,QAAQ,YAAY,EAAE;;EAGhC,IAAI,UACA,OAAO;EAGX,IAAI,MAAM,OACN,OAAO,KAAK,sBACR,SACA,OACA,MAAM,MAAM,UAAU,KACtB,MAAM,MAAM,QACf;EAGL,OAAO,KAAK,sBAAsB,SAAS,OAAO,KAAK,YAAY;;CAGvE,sBAAgC,SAAqB,OAAyB,QAAgB,SAA2B;EACrH,MAAM,UAAU,IAAI,QAAQ,MAAM,SAAS,QAAQ;EAEnD,IAAI,YAAY,QAAQ,EAAE;GACtB,QAAQ,IAAI,gBAAgB,kCAAkC;GAC9D,OAAO,IAAI,SAAS,KAAK,UAAU;IAAE;IAAQ;IAAS,CAAC,EAAE;IACrD;IACA;IACH,CAAC;;EAGN,QAAQ,IAAI,gBAAgB,4BAA4B;EACxD,OAAO,IAAI,SAAS,SAAS;GACzB;GACA;GACH,CAAC;;CAKN,MAAM,SACF,OAC6B;EAC7B,MAAM,YAAY,MAAM;EACxB,MAAM,iBAAiB,MAAM;EAC7B,MAAM,cAAc,MAAM;EAC1B,MAAM,kBAAkB,MAAM;EAC9B,MAAM,iBAAiB,MAAM;EAE7B,MAAM,SAAS,CAAC;EAEhB,MAAM,aAAa,KAAK;EACxB,MAAM,gBAAgB;EAEtB,IAAI;EAEJ,IAAI;GACA,MAAM,UAAU,KAAK,OAAO,OAAO,MAAM,MAAM,MAAM,OAAO;GAC5D,WAAW,MAAM,KAAK,WAAW,OAAO,SAAS,EAAE;GAInD,IACI,CAAC,MAAM,SACP,CAAC,MAAM,cACP,UACA,MAAM,WAAW,WAAW,SAC9B;IACE,IAAI,MAAM,eAAe,IAAI,WAAW,IAAI,EACxC,MAAM,eAAe,IAAI,WAAW,KAAK;IAG7C,MAAM,UAAU,CAAC,GAAG,MAAM,eAAe,CACpC,KAAK,QAAQ,IAAI,aAAa,CAAC,CAC/B,KAAK,IAAI;IAEd,MAAM,iBAAiB,IAAI,QAAQ,MAAM,SAAS,QAAQ;IAC1D,eAAe,IAAI,WAAW,OAAO,QAAQ;IAC7C,WAAW,IAAI,SAAS,SAAS;KAC7B,QAAQ,MAAM,SAAS,UAAU;KACjC,SAAS;KACZ,CAAC;IAEF,MAAM,aAAa;;YAEjB;GACN,MAAM,aAAa;GACnB,MAAM,gBAAgB;GAMtB,IAAI,CAAC,MAAM,YAAY;IACnB,MAAM,OAAO;IACb,MAAM,YAAY;IAClB,MAAM,SAAS;;;EAIvB,OAAO;;;;;;;;;;;;;;;CAgBX,MAAgB,WACZ,OACA,SACA,YAC6B;EAC7B,IAAI,IAAI;EACR,IAAI;EAEJ,OAAO,CAAC,MAAM,cAAc,IAAI,QAAQ,QAAQ;GAC5C,MAAM,QAAQ,QAAQ;GACtB,MAAM,UAAU,MAAM,MAAM;GAK5B,IACK,MAAM,SAAS,QAAQ,SAAS,YAAY,QAC5C,CAAC,MAAM,SAAS,QAAQ,SAAS,YAAY,OAChD;IACE;IACA;;GAGJ,MAAM,EAAE,WAAW,MAAM;GAEzB,IAAI,QACA,MAAM,eAAe,IAAI,OAAO;GAGpC,IAAI,CAAC,mBAAmB,QAAQ,MAAM,OAAqB,EAAE;IACzD;IACA;;GAGJ,iBAAiB,OAAO,MAAM,OAAO;GAMrC,MAAM,iBAAiB,MAAM;GAC7B,IAAI,OAAO,MAAM,SAAS,UACtB,MAAM,YAAY,MAAM;GAG5B,MAAM,kBAAkB;GACxB,MAAM,YAAY,IAAI;GAEtB,MAAM,QAAQ,OAAO,UAAkB;IACnC,IAAI,OACA,MAAM,QAAQ,YAAY,MAAM;IAEpC,OAAO,KAAK,WAAW,OAAO,iBAAiB,UAAU;KAC3D;GAEF,IAAI;IACA,MAAM,mBAAmB,MAAM,QAAQ,SAAS,MAAM;IAEtD,IAAI,kBAAkB;KAClB,WAAW;KACX,MAAM,aAAa;;YAElB,GAAG;IACR,MAAM,QAAQ,YAAY,EAAE;aAGtB;IACN,MAAM,YAAY;;GAGtB;;EAGJ,OAAO;;CASX,OAAO,GAAG,OAAkD;EACxD,KAAK,aAAa,WAAW,QAAQ,GAAG,MAAM;EAE9C,OAAO;;CAOX,IAAI,GAAG,OAAkD;EACrD,KAAK,aAAa,WAAW,KAAK,GAAG,MAAM;EAE3C,OAAO;;CAOX,KAAK,GAAG,OAAkD;EACtD,KAAK,aAAa,WAAW,MAAM,GAAG,MAAM;EAE5C,OAAO;;CAOX,IAAI,GAAG,OAAkD;EACrD,KAAK,aAAa,WAAW,KAAK,GAAG,MAAM;EAE3C,OAAO;;CAOX,MAAM,GAAG,OAAkD;EACvD,KAAK,aAAa,WAAW,OAAO,GAAG,MAAM;EAE7C,OAAO;;CAOX,KAAK,GAAG,OAAkD;EACtD,KAAK,aAAa,WAAW,MAAM,GAAG,MAAM;EAE5C,OAAO;;CAOX,QAAQ,GAAG,OAAkD;EACzD,KAAK,aAAa,WAAW,SAAS,GAAG,MAAM;EAE/C,OAAO;;CAKX,aACI,QACA,GAAG,OACL;EACE,IAAI;EAEJ,KAAK,MAAM,WAAW,OAAO;GACzB,IAAI,OAAO,QAAQ,EAAE;IACjB,OAAO;IACP;;GAGJ,IAAI;GAKJ,IAAI,UAAU,QAAQ,EAClB,UAAU;QACP,IAAI,iBAAiB,QAAQ,EAGhC,UAAU,IAAI,QAAQ;IAClB,GAAG;IACH;IACH,CAAC;QAEF;GAGJ,KAAK,SAAS;IACV,MAAM,UAAU,KAAK,OAAO,MAAM,QAAQ,KAAK;IAC/C;IACA,MAAM;IACT,CAAC;;;CAkBV,IAAI,GAAG,OAAwB;EAC3B,IAAI;EACJ,KAAK,MAAM,QAAQ,OAAO;GACtB,IAAI,OAAO,KAAK,EAAE;IACd,OAAO,iBAAiB,KAAK;IAC7B;;GAGJ,IAAI,cAAc,KAAK,EAAE;IACrB,KAAK,QAAQ,MAAM,KAAK;IACxB;;GAKJ,IAAI,UAAU,KAAK,EAAE;IACjB,KAAK,SAAS;KACV,MAAM,UAAU,KAAK,OAAO,MAAM,KAAK,KAAK;KAC5C,QAAQ,KAAK;KACb,MAAM;KACT,CAAC;IACF;;GAGJ,IAAI,iBAAiB,KAAK,EAAE;IACxB,MAAM,UAAU,IAAI,QAAQ,EAAE,GAAG,MAAM,CAAC;IAExC,KAAK,SAAS;KACV,MAAM,UAAU,KAAK,OAAO,MAAM,QAAQ,KAAK;KAC/C,QAAQ,QAAQ;KAChB,MAAM;KACT,CAAC;IACF;;GAGJ,IAAI,SAAS,KAAK,EACd,IAAI,MACA,KAAK,QAAQ,MAAM,EAAE,MAAM,CAAC;QAE5B,KAAK,QAAQ,KAAK;;EAK9B,OAAO;;;;;;;;;;;;CAaX,QAAkB,OAAa,MAA8B;EAIzD,KAAK,MAAM,SAAS,MAAM,QACtB,KAAK,SAAS;GACV,MAAM,UAAU,KAAK,OAAO,MAAM,MAAM,KAAK;GAC7C,QAAQ,MAAM;GACd,MAAM,MAAM;GACf,CAAC;EAQN,MAAM,mBAAmB,IAAI,IAAI,KAAK,SAAS,MAAM,CAAC;EAkBtD,KAAK,MAAM,CAAC,MAAM,eAAe,MAAM,SAAS;GAM5C,IAAI,KAAK,kBAAkB,IAAI,KAAK,EAChC;GAEJ,IAAI,QAAQ,KAAK,SAAS,IAAI,KAAK;GACnC,KAAK,MAAM,CAAC,UAAU,YAAY,YAAY;IAC1C,MAAM,cAAc,UAAU,KAAK,OAAO,MAAM,SAAS,IAAI;IAG7D,IAAI,SAAS,MAAM,IAAI,YAAY,EAC/B;IAEJ,IAAI,CAAC,OAAO;KACR,wBAAQ,IAAI,KAAK;KACjB,KAAK,SAAS,IAAI,MAAM,MAAM;;IAElC,MAAM,IAAI,aAAa,QAAQ;;;EAWvC,KAAK,MAAM,QAAQ,MAAM,kBACrB,IAAI,CAAC,iBAAiB,IAAI,KAAK,EAC3B,KAAK,kBAAkB,IAAI,KAAK;;;;;;CAW5C,UAAU,MAAuB;EAC7B,MAAM,QAAQ,KAAK,SAAS,IAAI,KAAK;EACrC,OAAO,CAAC,CAAC,SAAS,MAAM,OAAO;;;;;;;;CASnC,YAAY,MAAc,MAAsB;EAC5C,MAAM,QAAQ,KAAK,SAAS,IAAI,KAAK;EACrC,IAAI,CAAC,OACD,OAAO;EAEX,MAAM,MAAM,UAAU,KAAK,OAAO,KAAK,IAAI;EAC3C,OAAO,MAAM,IAAI,IAAI;;;;;;;;;;CAWzB,iBAAiB,MAAkC;EAC/C,MAAM,QAAQ,KAAK,SAAS,IAAI,KAAK;EACrC,IAAI,CAAC,OACD;EAEJ,MAAM,QAAQ,MAAM,QAAQ,CAAC,MAAM;EACnC,OAAO,MAAM,OAAO,KAAA,IAAY,MAAM;;;;;;;;CAS1C,mBAAmB,MAAc,MAAiC;EAC9D,MAAM,QAAQ,KAAK,SAAS,IAAI,KAAK;EACrC,IAAI,CAAC,OACD;EAEJ,OAAO,MAAM,IAAI,UAAU,KAAK,OAAO,KAAK,IAAI,IAAI;;;;;;;;CASxD,oBAAoB,MAAiC;EACjD,MAAM,QAAQ,KAAK,SAAS,IAAI,KAAK;EACrC,IAAI,CAAC,OACD,OAAO,EAAE;EAEb,OAAO,MAAM,KAAK,MAAM,MAAM,CAAC;;CAKnC,QACI,QACA,UAAgC,EAAE,EAC9B;EACJ,MAAM,WAAW,UAAU,KAAK,OAAO,QAAQ,KAAK,IAAI;EACxD,MAAM,WAAW,KAAK,SAAS,IAAI,OAAO,KAAK;EAM/C,IAAI,KAAK,kBAAkB,IAAI,OAAO,KAAK,EACvC,OAAO;EAOX,IAAI,OAAO,aAAa,YAAY,SAAS,OAAO,GAChD,OAAO;EAKX,IAAI,OAAO,mBAAmB,YAAY,SAAS,IAAI,SAAS,EAC5D,OAAO;EAQX,MAAM,UAAU,IAAI,IAAI,EAAE,MAAM,OAAO,MAAM,CAAC;EAC9C,OAAO,QAAQ,QAAQ;EAEvB,IAAI,QAAQ,MACR,KAAK,IAAI,QAAQ,MAAM,QAAQ;OAE/B,KAAK,IAAI,QAAQ;EAGrB,IAAI,QAAQ,KAAK,SAAS,IAAI,OAAO,KAAK;EAC1C,IAAI,CAAC,OAAO;GACR,wBAAQ,IAAI,KAAK;GACjB,KAAK,SAAS,IAAI,OAAO,MAAM,MAAM;;EAEzC,MAAM,IAAI,UAAU,OAAO,QAAQ;EAEnC,IAAI,OAAO,WACP,KAAK,kBAAkB,IAAI,OAAO,KAAK;EAG3C,OAAO"}