@interopio/gateway-server 0.21.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/http/exchange.ts", "../../src/client/exchange.ts", "../../src/http/status.ts", "../../src/client/fetch.ts", "../../src/mock/client/exchange.ts", "../../src/mock/server/exchange.ts", "../../src/server/exchange.ts", "../../src/logger.ts", "../../src/server/handler.ts", "../../src/test/server/handler.ts", "../../src/server/ws-client-verify.ts", "../../src/server/util/matchers.ts", "../../src/app/route.ts", "../../src/common/compose.ts", "../../src/test/server/client.ts", "../../src/test/index.ts"],
4
- "sourcesContent": ["import type {\n HeaderValues,\n HttpCookie,\n HttpHeaders,\n MutableHttpHeaders,\n ReadonlyHeaderValues,\n ResponseCookie\n} from '../../types/web/http';\nimport { type AddressInfo, isIP } from 'node:net';\nimport { Cookie } from 'tough-cookie';\n\nfunction parseHost(headers: HttpHeaders, defaultHost?: string): string | undefined {\n let host = headers.get('x-forwarded-host');\n if (Array.isArray(host)) {\n host = host[0];\n }\n if (host) {\n const port = headers.one('x-forwarded-port');\n if (port) {\n host = `${host}:${port}`;\n }\n }\n host ??= headers.one('host');\n if (Array.isArray(host)) {\n host = host[0];\n }\n if (host) {\n return (host as string).split(',', 1)[0].trim();\n }\n\n return defaultHost;\n}\n\nfunction isForwardedSsl(headers: HttpHeaders): boolean {\n const v = headers.one('x-forwarded-ssl');\n return (typeof v === 'string') && (v.toLowerCase() === 'on');\n}\n\nfunction parseProtocol(headers: HttpHeaders, defaultProtocol: string): string {\n let proto = headers.get('x-forwarded-proto');\n\n if (Array.isArray(proto)) {\n proto = proto[0];\n }\n if (proto !== undefined) {\n return (proto as string).split(',', 1)[0].trim();\n }\n else if (isForwardedSsl(headers)) {\n return 'https';\n }\n return defaultProtocol;\n}\n\nfunction parseRemoteAddress(url: URL, headers: HttpHeaders, remoteAddress?: AddressInfo) : AddressInfo | undefined {\n const port = remoteAddress ? remoteAddress.port : 'https:' === url.protocol ? 443 : 80;\n\n let host = headers.one('x-forwarded-for');\n if (Array.isArray(host)) {\n host = host[0];\n }\n if (host !== undefined) {\n host = (host as string).split(',', 1)[0].trim();\n return { address: host, port: Number(port), family: isIP(host) === 6 ? 'IPv6' : 'IPv4' };\n }\n}\n\nexport abstract class AbstractHttpMessage<Headers extends HttpHeaders = HttpHeaders> {\n readonly #headers: Headers;\n protected constructor(headers: Headers) {\n this.#headers = headers;\n }\n get headers(): Headers {\n return this.#headers;\n }\n}\n\nexport abstract class AbstractHttpRequest<Headers extends HttpHeaders = HttpHeaders> extends AbstractHttpMessage<Headers> {\n private static logIdCounter = 0;\n #id?: string\n\n get id(): string {\n if (this.#id === undefined) {\n this.#id = `${this.initId()}-${++AbstractHttpRequest.logIdCounter}`;\n\n }\n return this.#id;\n }\n\n protected initId(): string {\n return 'request';\n }\n\n get cookies(): HttpCookie[] {\n return parseCookies(this.headers);\n }\n\n protected parseHost(defaultHost?: string): string | undefined {\n return parseHost(this.headers, defaultHost);\n }\n\n protected parseProtocol(defaultProtocol: string): string {\n return parseProtocol(this.headers, defaultProtocol);\n }\n\n abstract get URL(): URL;\n\n protected parseRemoteAddress(remoteAddress?: AddressInfo) {\n return parseRemoteAddress(this.URL, this.headers, remoteAddress);\n }\n}\n\nexport abstract class AbstractHttpResponse<Headers extends HttpHeaders = HttpHeaders> extends AbstractHttpMessage<Headers> {\n get cookies(): ResponseCookie[] {\n return parseResponseCookies(this.headers);\n }\n\n protected setCookieValue(responseCookie: ResponseCookie): string {\n const cookie = new Cookie({\n key: responseCookie.name,\n value: responseCookie.value,\n maxAge: responseCookie.maxAge,\n domain: responseCookie.domain,\n path: responseCookie.path,\n secure: responseCookie.secure,\n httpOnly: responseCookie.httpOnly,\n sameSite: responseCookie.sameSite\n });\n return cookie.toString();\n }\n\n}\n\nfunction parseHeader(value: string): string[] {\n const list: string[] = [];\n {\n let start = 0;\n let end = 0;\n\n for (let i = 0; i < value.length; i++) {\n switch (value.charCodeAt(i)) {\n case 0x20: // space\n if (start === end) {\n start = end = i + 1;\n }\n break;\n case 0x2c: // comma\n list.push(value.slice(start, end));\n start = end = i + 1;\n break;\n default:\n end = end + 1;\n break;\n }\n }\n list.push(value.slice(start, end));\n }\n\n return list;\n}\n\nfunction toList(values: number | string | (readonly string[]) | undefined): string[] {\n if (typeof values === 'string') {\n values = [values];\n }\n if (typeof values === 'number') {\n values = [String(values)];\n }\n const list: string[] = [];\n if (values) {\n for (const value of values) {\n if (value) {\n list.push(...parseHeader(value));\n }\n }\n }\n return list;\n}\n\nfunction parseCookies(headers: HttpHeaders): HttpCookie[] {\n return headers.list('cookie')\n .map(s => s.split(';').map((cs) => Cookie.parse(cs)))\n .flat(1)\n .filter((tc) => tc !== undefined)\n .map((tc) => {\n const result: HttpCookie = Object.freeze({name: tc.key, value: tc.value});\n return result;\n });\n}\n\ntype Mutable<T> = {-readonly [K in keyof T]: T[K]};\n\nfunction parseResponseCookies(headers: HttpHeaders): ResponseCookie[] {\n return headers.list('set-cookie').map((cookie) => {\n const parsed = Cookie.parse(cookie);\n if (parsed) {\n const result: Mutable<ResponseCookie> = {name: parsed.key, value: parsed.value, maxAge: Number(parsed.maxAge ?? -1)};\n if (parsed.httpOnly) result.httpOnly = true;\n if (parsed.domain) result.domain = parsed.domain;\n if (parsed.path) result.path = parsed.path;\n if (parsed.secure) result.secure = true;\n if (parsed.httpOnly) result.httpOnly = true;\n if (parsed.sameSite) result.sameSite = parsed.sameSite as 'strict' | 'lax' | 'none';\n return Object.freeze(result);\n }\n }).filter((cookie): cookie is ResponseCookie => cookie !== undefined);\n}\n\n\nexport abstract class AbstractHttpHeaders<Values extends HeaderValues | ReadonlyHeaderValues> {\n protected constructor() {}\n abstract get(name: string): Values\n\n toList(name: string): string[] {\n const values = this.get(name);\n return toList(values);\n }\n}\n\nexport class MapHttpHeaders extends Map<string, (readonly string[])> implements MutableHttpHeaders {\n\n get(name: string) {\n return super.get(name.toLowerCase());\n }\n\n one(name: string): string | undefined {\n return this.get(name)?.[0];\n }\n\n list(name: string) {\n const values = super.get(name.toLowerCase());\n return toList(values);\n }\n\n set(name: string, value: number | string | (readonly string[]) | undefined): this {\n if (typeof value === 'number') {\n value = String(value);\n }\n if (typeof value === 'string') {\n value = [value];\n }\n if (value) {\n return super.set(name.toLowerCase(), value);\n }\n else {\n super.delete(name.toLowerCase());\n return this;\n }\n }\n\n add(name: string, value: string | (readonly string[])) {\n const prev = super.get(name.toLowerCase());\n if (typeof value === 'string') {\n value = [value];\n }\n if (prev) {\n value = prev.concat(value);\n }\n this.set(name, value);\n return this;\n }\n}\n", "import type {\n HttpMethod,\n HttpStatusCode,\n MutableHttpHeaders,\n ReadonlyHttpHeaders\n} from '../../types/web/http';\n\nimport {AbstractHttpRequest, AbstractHttpResponse, MapHttpHeaders} from '../http/exchange.ts';\n\nexport abstract class AbstractClientHttpRequest extends AbstractHttpRequest<MutableHttpHeaders> {\n\n protected constructor(method: HttpMethod, uri: URL) {\n super(new MapHttpHeaders());\n this.URL = uri;\n this.method = method;\n }\n\n readonly URL: URL;\n readonly method: HttpMethod;\n}\n\nexport abstract class AbstractClientHttpResponse extends AbstractHttpResponse<ReadonlyHttpHeaders> {\n protected constructor(statusCode: HttpStatusCode, headers: ReadonlyHttpHeaders) {\n super(headers);\n this.statusCode = statusCode;\n }\n readonly statusCode: HttpStatusCode;\n}\n", "import type {HttpStatusCode} from '../../types/web/http';\n\nclass DefaultHttpStatusCode implements HttpStatusCode {\n readonly #value: number;\n constructor(value: number) {\n this.#value = value;\n }\n get value(): number {\n return this.#value;\n }\n\n toString(): string {\n return this.#value.toString();\n }\n}\n\nexport class HttpStatus implements HttpStatusCode {\n static readonly CONTINUE = new HttpStatus(100, 'Continue');\n static readonly SWITCHING_PROTOCOLS = new HttpStatus(101, 'Switching Protocols');\n\n // 2xx Success\n\n static readonly OK = new HttpStatus(200, 'OK');\n static readonly CREATED = new HttpStatus(201, 'Created');\n static readonly ACCEPTED = new HttpStatus(202, 'Accepted');\n static readonly NON_AUTHORITATIVE_INFORMATION = new HttpStatus(203, 'Non-Authoritative Information');\n static readonly NO_CONTENT = new HttpStatus(204, 'No Content');\n static readonly RESET_CONTENT = new HttpStatus(205, 'Reset Content');\n static readonly PARTIAL_CONTENT = new HttpStatus(206, 'Partial Content');\n static readonly MULTI_STATUS = new HttpStatus(207, 'Multi-Status');\n\n static readonly IM_USED = new HttpStatus(226, 'IM Used');\n\n\n // 3xx Redirection\n static readonly MULTIPLE_CHOICES = new HttpStatus(300, 'Multiple Choices');\n static readonly MOVED_PERMANENTLY = new HttpStatus(301, 'Moved Permanently');\n\n // 4xx Client Error\n\n static readonly BAD_REQUEST = new HttpStatus(400, 'Bad Request');\n static readonly UNAUTHORIZED = new HttpStatus(401, 'Unauthorized');\n static readonly FORBIDDEN = new HttpStatus(403, 'Forbidden');\n static readonly NOT_FOUND = new HttpStatus(404, 'Not Found');\n static readonly METHOD_NOT_ALLOWED = new HttpStatus(405, 'Method Not Allowed');\n static readonly NOT_ACCEPTABLE = new HttpStatus(406, 'Not Acceptable');\n static readonly PROXY_AUTHENTICATION_REQUIRED = new HttpStatus(407, 'Proxy Authentication Required');\n static readonly REQUEST_TIMEOUT = new HttpStatus(408, 'Request Timeout');\n static readonly CONFLICT = new HttpStatus(409, 'Conflict');\n static readonly GONE = new HttpStatus(410, 'Gone');\n static readonly LENGTH_REQUIRED = new HttpStatus(411, 'Length Required');\n static readonly PRECONDITION_FAILED = new HttpStatus(412, 'Precondition Failed');\n static readonly PAYLOAD_TOO_LARGE = new HttpStatus(413, 'Payload Too Large');\n static readonly URI_TOO_LONG = new HttpStatus(414, 'URI Too Long');\n static readonly UNSUPPORTED_MEDIA_TYPE = new HttpStatus(415, 'Unsupported Media Type');\n\n static readonly EXPECTATION_FAILED = new HttpStatus(417, 'Expectation Failed');\n static readonly IM_A_TEAPOT = new HttpStatus(418, 'I\\'m a teapot');\n\n static readonly TOO_EARLY = new HttpStatus(425, 'Too Early');\n static readonly UPGRADE_REQUIRED = new HttpStatus(426, 'Upgrade Required');\n static readonly PRECONDITION_REQUIRED = new HttpStatus(428, 'Precondition Required');\n static readonly TOO_MANY_REQUESTS = new HttpStatus(429, 'Too Many Requests');\n static readonly REQUEST_HEADER_FIELDS_TOO_LARGE = new HttpStatus(431, 'Request Header Fields Too Large');\n static readonly UNAVAILABLE_FOR_LEGAL_REASONS = new HttpStatus(451, 'Unavailable For Legal Reasons');\n\n // 5xx Server Error\n static readonly INTERNAL_SERVER_ERROR = new HttpStatus(500, 'Internal Server Error');\n static readonly NOT_IMPLEMENTED = new HttpStatus(501, 'Not Implemented');\n static readonly BAD_GATEWAY = new HttpStatus(502, 'Bad Gateway');\n static readonly SERVICE_UNAVAILABLE = new HttpStatus(503, 'Service Unavailable');\n static readonly GATEWAY_TIMEOUT = new HttpStatus(504, 'Gateway Timeout');\n static readonly HTTP_VERSION_NOT_SUPPORTED = new HttpStatus(505, 'HTTP Version Not Supported');\n static readonly VARIANT_ALSO_NEGOTIATES = new HttpStatus(506, 'Variant Also Negotiates');\n static readonly INSUFFICIENT_STORAGE = new HttpStatus(507, 'Insufficient Storage');\n static readonly LOOP_DETECTED = new HttpStatus(508, 'Loop Detected');\n static readonly NOT_EXTENDED = new HttpStatus(510, 'Not Extended');\n static readonly NETWORK_AUTHENTICATION_REQUIRED = new HttpStatus(511, 'Network Authentication Required');\n\n static readonly #VALUES: HttpStatus[] = [];\n static {\n Object.keys(HttpStatus)\n .filter(key => key !== 'VALUES' && key !== 'resolve')\n .forEach(key => {\n const value = HttpStatus[key];\n if (value instanceof HttpStatus) {\n Object.defineProperty(value, 'name', { enumerable: true, value: key, writable: false });\n HttpStatus.#VALUES.push(value);\n }\n })\n\n }\n\n static resolve(code: number): HttpStatus | undefined {\n for (const status of HttpStatus.#VALUES) {\n if (status.value === code) {\n return status;\n }\n }\n }\n\n readonly #value: number;\n readonly #phrase: string;\n\n private constructor(value: number, phrase: string) {\n this.#value = value;\n this.#phrase = phrase;\n }\n\n get value(): number {\n return this.#value;\n }\n get phrase(): string {\n return this.#phrase;\n }\n\n toString() {\n return `${this.#value} ${this['name']}`;\n }\n}\n\n\nexport function httpStatusCode(value: number | HttpStatusCode): HttpStatusCode {\n if (typeof value === 'number') {\n if (value < 100 || value > 999) {\n throw new Error(`status code ${value} should be in range 100-999`);\n }\n const status = HttpStatus.resolve(value);\n if (status !== undefined) {\n return status;\n }\n return new DefaultHttpStatusCode(value);\n }\n return value;\n}\n", "import type { ClientHttpConnector } from './types.ts';\nimport { AbstractClientHttpRequest, AbstractClientHttpResponse } from './exchange.ts';\nimport { MapHttpHeaders } from \"../http/exchange.ts\";\n\nimport type {\n HttpMethod,\n BodyChunk\n} from '../../types/web/http';\nimport type {\n ClientHttpRequest,\n ClientHttpResponse\n} from '../../types/web/client';\nimport { httpStatusCode } from '../http/status.ts';\n\nclass FetchClientHttpRequest extends AbstractClientHttpRequest implements ClientHttpRequest {\n #body?: BodyInit;\n constructor(method: HttpMethod, uri: URL) {\n super(method, uri);\n }\n\n async body(body: ReadableStream<BodyChunk> | Promise<BodyChunk> | BodyChunk): Promise<boolean> {\n this.#body = body instanceof ReadableStream ? body : await body;\n return await this.end();\n }\n\n end() {\n return Promise.resolve(true);\n }\n\n getNativeRequest<T>(): T {\n const method = this.method;\n const headers = new Headers();\n for (const key of this.headers.keys()) {\n if (key.toLowerCase() === 'content-length') {\n continue; // Content-Length is set automatically later\n }\n for (const value of this.headers.list(key)) {\n headers.append(key, value);\n }\n }\n if (!this.headers.has('accept')) {\n headers.append('accept', '*/*');\n }\n const body = this.#body;\n\n return new Request(this.URL, {method, headers, body}) as T;\n }\n}\nfunction toHttpHeaders(headers: Headers): MapHttpHeaders {\n const result = new MapHttpHeaders();\n for (const [key, value] of headers.entries()) {\n result.add(key, value);\n }\n return result;\n}\nclass FetchClientHttpResponse extends AbstractClientHttpResponse implements ClientHttpResponse {\n #response: Response;\n constructor(response: Response) {\n super(httpStatusCode(response.status), toHttpHeaders(response.headers));\n this.#response = response;\n }\n\n get statusMessage() {\n return this.#response.statusText;\n }\n\n get body() {\n return this.#response.body ?? undefined;\n }\n\n blob() {\n return this.#response.blob();\n }\n}\n\nexport class FetchClientHttpConnector implements ClientHttpConnector {\n readonly #fetch: typeof fetch;\n constructor(fetchFn: typeof fetch = globalThis.fetch) {\n this.#fetch = fetchFn;\n }\n\n async connect(method: HttpMethod, uri: URL, requestCallback: (request: ClientHttpRequest) => Promise<void>): Promise<ClientHttpResponse> {\n const fetchClientHttpRequest = new FetchClientHttpRequest(method, uri);\n await requestCallback(fetchClientHttpRequest);\n const fetchRequest = fetchClientHttpRequest.getNativeRequest<Request>();\n const fetchResponse = await this.#fetch(fetchRequest);\n return new FetchClientHttpResponse(fetchResponse);\n }\n}\n", "import { AbstractClientHttpRequest } from '../../client/exchange.ts';\nimport {\n BodyChunk,\n HttpMethod,\n HttpStatusCode,\n type MutableHttpHeaders, type ReadonlyHeaderValue,\n ReadonlyHttpHeaders\n} from '../../../types/web/http';\nimport { ClientHttpRequest, ClientHttpResponse } from '../../../types/web/client';\n\nimport { AbstractHttpResponse, MapHttpHeaders } from '../../http/exchange.ts';\nimport { httpStatusCode } from '../../http/status.ts';\nimport * as stream from 'node:stream/web';\n\nexport class MockClientHttpRequest extends AbstractClientHttpRequest implements ClientHttpRequest {\n #writeHandler: (body: ReadableStream<BodyChunk>) => Promise<boolean>;\n #body: () => ReadableStream<BodyChunk> = () => {\n throw new Error(\"Body not set\");\n };\n constructor(uri: URL, method: HttpMethod) {\n super(method, uri);\n this.#writeHandler = async (body) => {\n const chunks: BodyChunk[] = [];\n this.#body = () => {\n return stream.ReadableStream.from(chunks) as ReadableStream<BodyChunk>;\n };\n const reader = body.getReader();\n let done: boolean;\n do {\n const {value, done: doneReading} = await reader.read();\n done = doneReading;\n if (value !== undefined) {\n chunks.push(value);\n }\n } while (!done);\n return true;\n }\n }\n set writeHandler(handler: (body: ReadableStream<BodyChunk>) => Promise<boolean>) {\n this.#writeHandler = handler;\n }\n\n getNativeRequest<T>(): T {\n return this as unknown as T;\n }\n\n getBody(): ReadableStream<BodyChunk> {\n return this.#body();\n }\n\n body(body: ReadableStream<BodyChunk> | Promise<BodyChunk | void> | BodyChunk): Promise<boolean> {\n const asyncIterator = (async function* () {\n if (body instanceof ReadableStream) {\n const reader = body.getReader();\n let done: boolean;\n do {\n const {value, done: doneReading} = await reader.read();\n done = doneReading;\n if (value !== undefined) {\n yield value;\n }\n } while (!done);\n }\n else {\n const value = await body;\n if (value !== undefined) {\n yield value;\n }\n }\n\n })();\n return this.#writeHandler(stream.ReadableStream.from(asyncIterator) as ReadableStream<BodyChunk>);\n }\n\n async end() {\n return await this.body(Promise.resolve());\n }\n\n}\n\nexport class MockClientHttpResponse extends AbstractHttpResponse<ReadonlyHttpHeaders> implements ClientHttpResponse {\n #statusCode: HttpStatusCode;\n #body: ReadableStream<BodyChunk> = stream.ReadableStream.from([]) as ReadableStream<BodyChunk>;\n constructor(status: number | HttpStatusCode) {\n super(new MapHttpHeaders());\n this.#statusCode = httpStatusCode(status);\n }\n\n get statusCode(): HttpStatusCode {\n return this.#statusCode;\n }\n\n addHeader(name: string, value: string | (readonly string[])): this {\n (this.headers as MutableHttpHeaders).add(name, value);\n return this;\n }\n\n setHeader(name: string, value: ReadonlyHeaderValue): this {\n (this.headers as MutableHttpHeaders).set(name, value);\n return this;\n }\n\n setBody(body: string, charset?: BufferEncoding): this {\n this.#body = stream.ReadableStream.from([Buffer.from(body, charset)]) as ReadableStream<BodyChunk>;\n return this;\n }\n\n set body(body: ReadableStream<BodyChunk>) {\n this.#body = body;\n }\n\n get body() {\n return this.#body;\n }\n\n async blob() {\n const chunks: BodyChunk[] = [];\n if (this.body !== undefined) {\n for await (const chunk of this.body) {\n chunks.push(chunk);\n }\n }\n return new Blob(chunks, {type: this.headers.one('content-type') as string || 'application/octet-stream'});\n }\n}\n", "import { AbstractHttpRequest, MapHttpHeaders } from '../../http/exchange.ts';\nimport type {\n BodyChunk,\n HttpMethod, HttpResponse,\n MutableHttpHeaders,\n ReadonlyHeaderValue,\n ReadonlyHttpHeaders\n} from '../../../types/web/http';\nimport { ServerHttpRequest } from '../../../types/web/server';\nimport stream from 'node:stream/web';\nimport { AbstractServerHttpResponse, DefaultWebExchange } from '../../server/exchange.ts';\nimport type { Principal } from '../../../types/auth';\n\nexport class MockServerHttpRequest extends AbstractHttpRequest<ReadonlyHttpHeaders> implements ServerHttpRequest {\n readonly #url: URL;\n #body?: Blob;\n upgrade = false;\n\n constructor(url: URL | string, method?: HttpMethod) {\n super(new MapHttpHeaders());\n if (typeof url === 'string') {\n if (URL.canParse(url)) {\n url = new URL(url);\n }\n else if (URL.canParse(url, 'http://localhost')) {\n url = new URL(url, 'http://localhost');\n }\n else {\n throw new TypeError('URL cannot parse url');\n }\n }\n this.#url = url;\n this.method = method ?? 'GET';\n this.setHeader('Host', this.#url.hostname);\n this.path = this.#url.pathname ?? '/';\n }\n\n method: HttpMethod;\n path: string;\n\n get host() {\n return super.parseHost(this.#url.host);\n }\n\n get protocol() {\n return super.parseProtocol((this.#url.protocol).slice(0, -1));\n }\n\n get body() {\n if (this.#body !== undefined) {\n const blob = this.#body;\n const asyncIterator: AsyncGenerator<BodyChunk> = (async function* () {\n const bytes = await blob.bytes();\n yield bytes;\n })();\n return stream.ReadableStream.from(asyncIterator) as ReadableStream<BodyChunk>;\n }\n }\n\n blob(): Promise<Blob> {\n const body = this.#body;\n return body ? Promise.resolve(body) : Promise.reject(new Error(`no body set`));\n }\n\n async text() {\n const blob = await this.blob();\n return await blob.text();\n }\n\n async formData() {\n const blob = await this.blob();\n const text = await blob.text();\n return new URLSearchParams(text);\n }\n\n async json() {\n const blob = await this.blob();\n if (blob.size === 0) {\n return undefined;\n }\n const text = await blob.text();\n return JSON.parse(text);\n }\n\n async writeBody(body?: ReadableStream<BodyChunk> | Promise<BodyChunk> | BodyChunk) {\n if (body === undefined) {\n this.#body = new Blob([]);\n return;\n }\n if (body instanceof ReadableStream) {\n const chunks: BodyChunk[] = [];\n const reader = body.getReader();\n let done = false;\n while (!done) {\n const { value, done: readDone } = await reader.read();\n if (readDone) {\n done = true;\n }\n else {\n chunks.push(value);\n }\n }\n this.#body = new Blob(chunks);\n }\n else {\n body = await body;\n if (typeof body === 'string') {\n this.#body = new Blob([body], { type: 'text/plain' });\n }\n else {\n this.#body = new Blob([body]);\n }\n }\n if (!this.headers.has('content-type')) {\n this.setHeader('Content-Type', this.#body.type || 'application/octet-stream');\n }\n\n }\n\n get URL() {\n return new URL(this.path + this.#url.search + this.#url.hash, `${this.protocol}://${this.host}`);\n }\n\n addHeader(name: string, value: string | (readonly string[])): this {\n (this.headers as MutableHttpHeaders).add(name, value);\n return this;\n }\n\n setHeader(name: string, value: ReadonlyHeaderValue): this {\n (this.headers as MutableHttpHeaders).set(name, value);\n return this;\n }\n}\n\nexport class MockServerHttpResponse extends AbstractServerHttpResponse implements HttpResponse<MutableHttpHeaders> {\n #writeHandler: (body: ReadableStream<BodyChunk>) => Promise<boolean>;\n #body: () => ReadableStream<BodyChunk> = () => {\n throw new Error('No content was written to the response body nor end was called on this response.');\n };\n\n constructor() {\n super(new MapHttpHeaders());\n this.#writeHandler = async (body) => {\n const chunks: BodyChunk[] = [];\n let bodyStream: ReadableStream<BodyChunk> | undefined;\n this.#body = () => {\n bodyStream ??= stream.ReadableStream.from(chunks) as ReadableStream<BodyChunk>;\n return bodyStream;\n };\n\n const reader = body.getReader();\n let done = false;\n do {\n const { value, done: readDone } = await reader.read();\n if (readDone) {\n done = true;\n }\n else {\n chunks.push(value);\n }\n }\n while (!done);\n return true;\n }\n }\n\n get statusCode() {\n return super.statusCode!; // :(\n }\n\n set writeHandler(handler: (body: ReadableStream<BodyChunk>) => Promise<boolean>) {\n this.#body = () => {\n throw new Error('Not available with custom write handler');\n }\n this.#writeHandler = handler;\n }\n\n\n getNativeResponse<T>(): T {\n throw new Error('This is a mock. No running server, no native response.');\n }\n\n protected applyStatusCode(): void {\n }\n\n protected applyHeaders(): void {\n }\n\n protected applyCookies(): void {\n for (const cookie of this.cookies) {\n this.headers.add('Set-Cookie', super.setCookieValue(cookie));\n }\n }\n\n bodyInternal(body: Promise<BodyChunk | void>): Promise<boolean> {\n const it = (async function* () {\n const resolved = await body;\n if (resolved === undefined) {\n return;\n }\n yield resolved;\n })();\n return this.#writeHandler(stream.ReadableStream.from(it) as ReadableStream<BodyChunk>);\n }\n\n async end(): Promise<boolean> {\n return this.doCommit(async () => {\n return await this.#writeHandler(stream.ReadableStream.from([]) as ReadableStream);\n });\n }\n\n getBody() {\n return this.#body();\n }\n}\n\n\nexport class MockWebExchange extends DefaultWebExchange<MockServerHttpRequest, MockServerHttpResponse> {\n readonly #principal?: Principal;\n\n constructor(request: MockServerHttpRequest, response?: MockServerHttpResponse, principal?: Principal) {\n super(request, response ?? new MockServerHttpResponse());\n this.#principal = principal;\n }\n\n principal<P extends Principal>(): Promise<P | undefined> {\n return Promise.resolve(this.#principal as P);\n }\n}\n", "import type { Principal } from '../../types/auth';\nimport type {\n BodyChunk,\n HeaderValue,\n HeaderValues,\n HttpCookie,\n HttpMethod,\n HttpStatusCode,\n MutableHttpHeaders,\n ReadonlyHeaderValues,\n ReadonlyHttpHeaders,\n ResponseCookie\n} from '../../types/web/http'\n\nimport type {\n ServerHttpRequest,\n ServerHttpResponse,\n ServerWebExchange,\n SslInfo\n} from '../../types/web/server';\nimport { AbstractHttpHeaders, AbstractHttpRequest, AbstractHttpResponse } from '../http/exchange.ts';\nimport { httpStatusCode } from '../http/status.ts';\nimport type { X509Certificate} from 'node:crypto';\nimport http from 'node:http';\nimport http2 from 'node:http2';\nimport net from 'node:net';\nimport type { TLSSocket } from 'node:tls';\n\nexport class ExtendedHttpIncomingMessage extends http.IncomingMessage {\n // circular reference to the exchange\n exchange?: ServerWebExchange;\n\n upgradeHead?: Buffer<ArrayBufferLike>\n\n\n get urlBang(): string {\n return this.url!;\n }\n\n get socketEncrypted(): boolean {\n // see tls.TLSSocket#encrypted\n return this.socket['encrypted'] === true;\n }\n}\n\nexport class ExtendedHttpServerResponse<Request extends ExtendedHttpIncomingMessage = ExtendedHttpIncomingMessage> extends http.ServerResponse<Request> {\n\n markHeadersSent(): void {\n this['_header'] = true; // prevent response from being sent\n }\n\n getRawHeaderNames(): string[] {\n return super['getRawHeaderNames']();\n }\n}\n\nabstract class AbstractServerHttpRequest extends AbstractHttpRequest<ReadonlyHttpHeaders> {\n #sslInfo?: SslInfo\n\n abstract getNativeRequest<T>(): T;\n\n protected abstract initSslInfo(): SslInfo | undefined;\n\n get sslInfo(): SslInfo | undefined {\n if (this.#sslInfo === undefined) {\n this.#sslInfo = this.initSslInfo();\n }\n return this.#sslInfo;\n }\n}\n\nexport abstract class AbstractServerHttpResponse extends AbstractHttpResponse<MutableHttpHeaders> {\n #cookies: ResponseCookie[] = [];\n #statusCode?: HttpStatusCode;\n #state: 'new' | 'committing' | 'commit-action-failed' | 'committed' = 'new';\n #commitActions: (() => Promise<void>)[] = [];\n\n setStatusCode(statusCode?: HttpStatusCode): boolean {\n if (this.#state === 'committed') {\n return false;\n }\n else {\n this.#statusCode = statusCode;\n return true;\n }\n }\n\n setRawStatusCode(statusCode?: number): boolean {\n return this.setStatusCode(statusCode === undefined ? undefined : httpStatusCode(statusCode));\n };\n\n get statusCode(): HttpStatusCode | undefined {\n return this.#statusCode;\n }\n\n addCookie(cookie: ResponseCookie): this {\n if (this.#state === 'committed') {\n throw new Error(`Cannot add cookie ${JSON.stringify(cookie)} because HTTP response has already been committed`);\n }\n this.#cookies.push(cookie);\n return this;\n }\n\n abstract getNativeResponse<T>(): T;\n\n beforeCommit(action: () => Promise<void>): void {\n this.#commitActions.push(action);\n }\n\n get commited(): boolean {\n const state = this.#state;\n return state !== 'new' && state !== 'commit-action-failed';\n }\n\n async body(body: ReadableStream<BodyChunk> | Promise<BodyChunk | void> | BodyChunk): Promise<boolean> {\n if (body instanceof ReadableStream) {\n throw new Error('ReadableStream body not supported yet');\n }\n const buffer = await body;\n try {\n // touch buffers if needed\n\n return await this.doCommit(async () => {\n\n return await this.bodyInternal(Promise.resolve(buffer));\n\n }).catch(error => {\n // release buffers\n throw error;\n });\n }\n catch (error) {\n // clear content headers\n throw error;\n }\n }\n\n abstract bodyInternal(body: Promise<BodyChunk | void>): Promise<boolean>;\n\n async end(): Promise<boolean> {\n if (!this.commited) {\n return this.doCommit(async () => {\n return await this.bodyInternal(Promise.resolve());\n });\n }\n else {\n return Promise.resolve(false);\n }\n }\n\n protected doCommit(writeAction?: () => Promise<boolean>): Promise<boolean> {\n const state = this.#state;\n let allActions = Promise.resolve();\n if (state === 'new') {\n this.#state = 'committing';\n if (this.#commitActions.length > 0) {\n allActions = this.#commitActions\n .reduce(\n (acc, cur) => acc.then(() => cur()),\n Promise.resolve())\n .catch((_error) => {\n const state = this.#state;\n if (state === 'committing') {\n this.#state = 'commit-action-failed';\n // clear content headers\n }\n });\n }\n }\n else if (state === 'commit-action-failed') {\n this.#state = 'committing';\n // skip commit actions\n } else {\n return Promise.resolve(false);\n }\n\n allActions = allActions.then(() => {\n this.applyStatusCode();\n this.applyHeaders();\n this.applyCookies();\n this.#state = 'committed';\n });\n\n\n return allActions.then(async () => {\n return writeAction !== undefined ? await writeAction() : true;\n });\n }\n\n protected applyStatusCode(): void {}\n protected applyHeaders(): void {}\n protected applyCookies(): void {}\n}\nexport class HttpServerRequest extends AbstractServerHttpRequest implements ServerHttpRequest {\n\n #url?: URL;\n #cookies?: HttpCookie[];\n readonly #req: ExtendedHttpIncomingMessage;\n\n constructor(req: ExtendedHttpIncomingMessage) {\n super(new IncomingMessageHeaders(req));\n this.#req = req;\n }\n\n getNativeRequest<T>(): T {\n return this.#req as T;\n }\n\n get upgrade() {\n return this.#req['upgrade'];\n }\n\n get http2(): boolean {\n return this.#req.httpVersionMajor >= 2;\n }\n\n get path() {\n return this.URL?.pathname;\n }\n\n get URL() {\n this.#url ??= new URL(this.#req.urlBang, `${this.protocol}://${this.host}`);\n return this.#url;\n }\n\n get query() {\n return this.URL?.search;\n }\n\n get method() {\n return this.#req.method as HttpMethod;\n }\n\n get host() {\n let dh: string | undefined = undefined;\n if (this.#req.httpVersionMajor >= 2) {\n dh = (this.#req.headers as http2.IncomingHttpHeaders)[':authority'];\n }\n dh ??= this.#req.socket.remoteAddress;\n return super.parseHost(dh);\n }\n\n get protocol() {\n let dp: string | undefined = undefined;\n if (this.#req.httpVersionMajor > 2) {\n dp = (this.#req.headers as http2.IncomingHttpHeaders)[':scheme'];\n }\n dp ??= this.#req.socketEncrypted ? 'https' : 'http';\n return super.parseProtocol(dp);\n }\n\n get socket() {\n return this.#req.socket;\n }\n\n get remoteAddress(): net.AddressInfo | undefined {\n const family = this.#req.socket.remoteFamily;\n const address = this.#req.socket.remoteAddress;\n const port = this.#req.socket.remotePort;\n const remoteAddress = (!family || !address || !port) ? undefined : { family, address, port };\n return super.parseRemoteAddress(remoteAddress) ?? remoteAddress;\n }\n\n protected initSslInfo(): SslInfo | undefined {\n if (this.#req.socketEncrypted) {\n return new DefaultSslInfo(this.#req.socket as TLSSocket);\n }\n }\n\n get cookies(): HttpCookie[] {\n this.#cookies ??= super.cookies\n return this.#cookies;\n }\n\n get body(): ReadableStream<BodyChunk> {\n return http.IncomingMessage.toWeb(this.#req) as ReadableStream<BodyChunk>;\n }\n\n async blob() {\n const chunks: BodyChunk[] = [];\n if (this.body !== undefined) {\n for await (const chunk of this.body) {\n chunks.push(chunk);\n }\n }\n return new Blob(chunks, {type: this.headers.one('content-type') as string || 'application/octet-stream'});\n }\n\n\n async text() {\n const blob = await this.blob();\n return await blob.text();\n }\n\n async formData() {\n const blob = await this.blob();\n const text = await blob.text();\n return new URLSearchParams(text);\n }\n\n async json() {\n const blob = await this.blob();\n if (blob.size === 0) {\n return undefined;\n }\n const text = await blob.text();\n return JSON.parse(text);\n }\n\n\n protected initId(): string {\n const remoteIp = this.#req.socket.remoteAddress;\n if (!remoteIp) {\n throw new Error('Socket has no remote address');\n }\n return `${remoteIp}:${this.#req.socket.remotePort}`;\n }\n}\n\nclass DefaultSslInfo implements SslInfo {\n readonly peerCertificate?: X509Certificate;\n constructor(socket: TLSSocket) {\n this.peerCertificate = socket.getPeerX509Certificate();\n }\n}\n\nclass IncomingMessageHeaders extends AbstractHttpHeaders<ReadonlyHeaderValues> implements ReadonlyHttpHeaders {\n readonly #msg: ExtendedHttpIncomingMessage;\n\n constructor(msg: ExtendedHttpIncomingMessage) {\n super();\n this.#msg = msg;\n }\n\n has(name: string): boolean {\n return this.#msg.headers[name] !== undefined;\n }\n\n get(name: string): string | (readonly string[]) | undefined {\n return this.#msg.headers[name];\n }\n\n list(name: string): string[] {\n return super.toList(name);\n }\n\n one(name: string): string | undefined {\n const value = this.#msg.headers[name];\n if (Array.isArray(value)) {\n return value[0];\n }\n return value;\n }\n\n keys() {\n return Object.keys(this.#msg.headers).values();\n }\n}\n\nclass OutgoingMessageHeaders extends AbstractHttpHeaders<HeaderValues> implements MutableHttpHeaders {\n readonly #msg: ExtendedHttpServerResponse;\n\n constructor(msg: ExtendedHttpServerResponse) {\n super();\n this.#msg = msg;\n }\n\n has(name: string): boolean {\n return this.#msg.hasHeader(name);\n }\n\n keys() {\n return this.#msg.getHeaderNames().values();\n }\n\n get(name: string): HeaderValues {\n return this.#msg.getHeader(name);\n }\n\n one(name: string): HeaderValue {\n const value = this.#msg.getHeader(name);\n if (Array.isArray(value)) {\n return value[0];\n }\n return value;\n }\n\n set(name: string, value: HeaderValues): this {\n if (!this.#msg.headersSent) {\n if (Array.isArray(value)) {\n value = value.map(v => typeof v === 'number' ? String(v) : v);\n } else if (typeof value === 'number') {\n value = String(value);\n }\n\n if (value) {\n this.#msg.setHeader(name, value);\n }\n else {\n this.#msg.removeHeader(name);\n }\n }\n return this;\n }\n\n add(name: string, value: string | (readonly string[])): this {\n if (!this.#msg.headersSent) {\n this.#msg.appendHeader(name, value);\n }\n return this;\n }\n\n list(name: string): string[] {\n return super.toList(name);\n }\n}\n\nexport class HttpServerResponse extends AbstractServerHttpResponse implements ServerHttpResponse {\n readonly #res: ExtendedHttpServerResponse;\n\n constructor(res: ExtendedHttpServerResponse) {\n super(new OutgoingMessageHeaders(res));\n this.#res = res;\n }\n\n getNativeResponse<T>(): T {\n return this.#res as T;\n }\n\n get statusCode(): HttpStatusCode {\n const status = super.statusCode;\n return status ?? {value: this.#res.statusCode};\n }\n\n applyStatusCode() {\n const status = super.statusCode;\n if (status !== undefined) {\n this.#res.statusCode = status.value;\n }\n }\n\n addCookie(cookie: ResponseCookie): this {\n this.headers.add('Set-Cookie', super.setCookieValue(cookie));\n return this;\n }\n\n async bodyInternal(body: Promise<BodyChunk | void>): Promise<boolean> {\n if (!this.#res.headersSent) {\n if (body instanceof ReadableStream) {\n // http.IncomingMessage.fromWeb(body)\n throw new Error('ReadableStream body not supported in response');\n }\n else {\n const chunk = await body;\n return await new Promise<boolean>((resolve, reject) => {\n try {\n if (chunk === undefined) {\n this.#res.end(() => {\n resolve(true);\n });\n } else {\n if (!this.headers.has('content-length')) {\n // set Content-Length if not already set\n if (typeof chunk === 'string') {\n this.headers.set('Content-Length', Buffer.byteLength(chunk));\n }\n else if (chunk instanceof Blob) {\n this.headers.set('Content-Length', chunk.size);\n }\n else {\n this.headers.set('Content-Length', chunk.byteLength);\n }\n }\n this.#res.end(chunk, () => {\n resolve(true);\n });\n }\n } catch (e) {\n reject(e instanceof Error ? e : new Error(`end failed: ${e}`));\n }\n });\n }\n }\n else {\n return false; // already ended\n }\n }\n}\n\nexport class ServerHttpRequestDecorator implements ServerHttpRequest {\n readonly #delegate: ServerHttpRequest;\n\n constructor(request: ServerHttpRequest) {\n this.#delegate = request;\n }\n\n get delegate(): ServerHttpRequest {\n return this.#delegate;\n }\n\n get id(): string {\n return this.#delegate.id;\n }\n\n get method(): HttpMethod {\n return this.#delegate.method;\n }\n\n get path(): string {\n return this.#delegate.path;\n }\n\n get protocol() {\n return this.#delegate.protocol;\n }\n\n get host(): string | undefined {\n return this.#delegate.host;\n }\n\n get URL(): URL {\n return this.#delegate.URL;\n }\n\n get headers(): ReadonlyHttpHeaders {\n return this.#delegate.headers;\n }\n\n get cookies(): HttpCookie[] {\n return this.#delegate.cookies;\n }\n\n get remoteAddress() {\n return this.#delegate.remoteAddress;\n }\n\n get upgrade() {\n return this.#delegate.upgrade;\n }\n\n get sslInfo() {\n return this.#delegate.sslInfo;\n }\n\n get body(): ReadableStream<BodyChunk> | undefined {\n return this.#delegate.body;\n }\n async blob(): Promise<Blob> {\n return await this.#delegate.blob();\n }\n async text(): Promise<string> {\n return await this.#delegate.text();\n }\n async formData(): Promise<URLSearchParams> {\n return await this.#delegate.formData();\n }\n async json(): Promise<unknown> {\n return await this.#delegate.json();\n }\n\n toString(): string {\n return `${ServerHttpRequestDecorator.name} [delegate: ${this.delegate.toString()}]`;\n }\n\n public static getNativeRequest<T>(request: ServerHttpRequest): T {\n if (request instanceof AbstractServerHttpRequest) {\n return request.getNativeRequest<T>();\n }\n else if (request instanceof ServerHttpRequestDecorator) {\n return ServerHttpRequestDecorator.getNativeRequest<T>(request.delegate);\n }\n else {\n throw new Error(`Cannot get native request from ${request.constructor.name}`);\n }\n }\n}\nexport class ServerHttpResponseDecorator implements ServerHttpResponse {\n readonly #delegate: ServerHttpResponse;\n\n constructor(response: ServerHttpResponse) {\n this.#delegate = response;\n }\n\n get delegate(): ServerHttpResponse {\n return this.#delegate;\n }\n\n setStatusCode(statusCode: HttpStatusCode): boolean {\n return this.delegate.setStatusCode(statusCode);\n }\n\n setRawStatusCode(statusCode?: number): boolean {\n return this.delegate.setRawStatusCode(statusCode);\n }\n\n get statusCode(): HttpStatusCode {\n return this.delegate.statusCode;\n }\n\n get cookies(): ResponseCookie[] {\n return this.delegate.cookies;\n }\n\n addCookie(cookie: ResponseCookie): this {\n this.delegate.addCookie(cookie);\n return this;\n }\n\n async end(): Promise<boolean> {\n return await this.delegate.end();\n }\n\n async body(body: ReadableStream<BodyChunk> | Promise<BodyChunk | void> | BodyChunk): Promise<boolean> {\n return await this.#delegate.body(body);\n }\n\n get headers(): MutableHttpHeaders {\n return this.#delegate.headers;\n }\n\n toString(): string {\n return `${ServerHttpResponseDecorator.name} [delegate: ${this.delegate.toString()}]`;\n }\n\n public static getNativeResponse<T>(response: ServerHttpResponse): T {\n if (response instanceof AbstractServerHttpResponse) {\n return response.getNativeResponse<T>();\n }\n else if (response instanceof ServerHttpResponseDecorator) {\n return ServerHttpResponseDecorator.getNativeResponse<T>(response.delegate);\n }\n else {\n throw new Error(`Cannot get native response from ${response.constructor.name}`);\n }\n }\n}\n\nexport class ServerWebExchangeDecorator implements ServerWebExchange {\n readonly #delegate: ServerWebExchange;\n\n protected constructor(exchange: ServerWebExchange) {\n this.#delegate = exchange;\n }\n\n get delegate(): ServerWebExchange {\n return this.#delegate;\n }\n\n get request(): ServerHttpRequest {\n return this.#delegate.request;\n }\n\n get response(): ServerHttpResponse {\n return this.#delegate.response;\n }\n\n attribute<T>(name: string): T | undefined {\n return this.#delegate.attribute(name);\n }\n\n principal<P extends Principal>(): Promise<P | undefined> {\n return this.#delegate.principal();\n }\n\n get logPrefix(): string {\n return this.#delegate.logPrefix;\n }\n\n toString() {\n return `${ServerWebExchangeDecorator.name} [delegate: ${this.delegate}]`;\n }\n}\n\nexport class DefaultWebExchange<Request extends ServerHttpRequest, Response extends ServerHttpResponse> {\n readonly request: Request;\n readonly response: Response;\n readonly #attributes: Record<string, unknown> = {};\n #logId?: unknown;\n #logPrefix: string = '';\n\n constructor(request: Request, response: Response) {\n this.#attributes[LOG_ID_ATTRIBUTE] = request.id;\n this.request = request;\n this.response = response;\n }\n\n get method(): HttpMethod {\n return this.request.method;\n }\n\n get path(): string | null | undefined {\n return this.request.path;\n }\n\n get attributes(): Record<string, unknown> {\n return this.#attributes;\n }\n\n attribute<T>(name: string): T | undefined {\n return this.attributes[name] as T;\n }\n\n principal<P extends Principal>(): Promise<P | undefined> {\n return Promise.resolve(undefined);\n }\n\n get logPrefix(): string {\n const value = this.attribute(LOG_ID_ATTRIBUTE);\n if (this.#logId !== value) {\n this.#logId = value;\n this.#logPrefix = value !== undefined ? `[${value}] ` : '';\n }\n return this.#logPrefix;\n }\n}\n\nexport const LOG_ID_ATTRIBUTE = 'io.interop.gateway.server.log_id';\n\n", "import * as GatewayLogging from '@interopio/gateway/logging/core';\n\nexport type Logger = GatewayLogging.Logger;\n\nexport default function getLogger(name: string): Logger {\n return GatewayLogging.getLogger(`gateway.server.${name}`);\n}\n\n// This function is used to ensure that RegExp objects are displayed correctly when logging.\nexport function regexAwareReplacer<T>(_key: string, value: T): string | T {\n return value instanceof RegExp ? value.toString() : value;\n}\n", "import type { HttpHandler, Middleware, WebHandler } from './types';\nimport { DefaultWebExchange, ServerHttpResponseDecorator } from './exchange.ts';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Logger } from '@interopio/gateway/logging/api';\nimport type { HttpHeaders } from '../../types/web/http';\nimport type {\n ServerHttpRequest,\n ServerHttpResponse,\n ServerWebExchange\n} from '../../types/web/server';\nimport getLogger from '../logger.ts';\nimport { HttpStatus } from '../http/status.ts';\n\nexport class HttpHeadResponseDecorator extends ServerHttpResponseDecorator {\n\n}\n\nfunction checkAndLogClientDisconnectedError(error: Error, logger: Logger): boolean {\n if (error === null || error === undefined) {\n return false;\n }\n const { code, message } = error as any;\n const isClientDisconnected =\n code === 'ECONNRESET' ||\n code === 'EPIPE' ||\n code === 'ERR_STREAM_PREMATURE_CLOSE' ||\n message?.toLowerCase().includes('client aborted') ||\n message?.toLowerCase().includes('socket hang up') ||\n message?.toLowerCase().includes('aborted');\n if (isClientDisconnected) {\n if (logger.enabledFor('trace')) {\n logger.trace('looks like the client has gone away:', error);\n }\n else if (logger.enabledFor('debug')) {\n logger.debug(`looks like the client has gone away: ${error.message} (For full stack trace enable trace logging level.)`);\n }\n return true;\n }\n return false;\n}\n\nclass HandlerAdapter {\n\n readonly #logger: Logger\n #enableLoggingRequestDetails: boolean = false;\n readonly #delegate: WebHandler;\n #storage?: AsyncLocalStorage<{ exchange: ServerWebExchange }>;\n\n constructor(logger: Logger, delegate: WebHandler) {\n this.#logger = logger;\n this.#delegate = delegate;\n }\n\n protected createExchange(request: ServerHttpRequest, response: ServerHttpResponse): ServerWebExchange {\n\n const exchange = new DefaultWebExchange(request, response);\n return exchange;\n }\n\n set storage(storage: AsyncLocalStorage<{ exchange: ServerWebExchange }>) {\n this.#storage = storage;\n }\n\n set enableLoggingRequestDetails(value: boolean) {\n this.#enableLoggingRequestDetails = value;\n }\n\n formatHeaders(headers: HttpHeaders): string {\n let result = '{';\n\n for (const key of headers.keys()) {\n if (!this.#enableLoggingRequestDetails) {\n result += 'masked, ';\n break;\n } else {\n const value = headers.get(key);\n result += `\"${key}\": \"${value}\", `;\n }\n }\n if (result.endsWith(', ')) {\n result = result.slice(0, -2);\n }\n result += '}';\n return result;\n\n }\n\n formatRequest(request: ServerHttpRequest): string {\n const query = request.URL.search;\n return `HTTP ${request.method} \"${request.path}${query}`;\n }\n\n logRequest(exchange: ServerWebExchange) {\n if (this.#logger.enabledFor('debug')) {\n const trace = this.#logger.enabledFor('trace');\n this.#logger.debug(`${exchange.logPrefix}${this.formatRequest(exchange.request)}${trace ? `, headers: ${this.formatHeaders(exchange.request.headers)}` : ''}\"`);\n\n }\n }\n\n logResponse(exchange: ServerWebExchange) {\n if (this.#logger.enabledFor('debug')) {\n const trace = this.#logger.enabledFor('trace');\n const status = exchange.response.statusCode;\n this.#logger.debug(`${exchange.logPrefix}Completed ${status ?? '200 OK'}${trace ? `, headers: ${this.formatHeaders(exchange.response.headers)}` : ''}\"`);\n }\n }\n\n handleUnresolvedError(exchange: ServerWebExchange, error: Error) {\n const {request, response, logPrefix} = exchange;\n\n if (response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR)) {\n this.#logger.error(`${logPrefix}500 Server Error for ${this.formatRequest(request)}`, error);\n return;\n }\n if (checkAndLogClientDisconnectedError(error, this.#logger)) {\n // todo notify observers\n return;\n }\n\n this.#logger.error(`${logPrefix}Error [${error.message} for ${this.formatRequest(request)}, but already ended (${response.statusCode})`, error);\n throw error;\n\n }\n\n async web(exchange: ServerWebExchange): Promise<void> {\n return await this.#delegate(exchange);\n }\n\n async http(request: ServerHttpRequest, response: ServerHttpResponse): Promise<void> {\n\n const exchange = this.createExchange(request, response);\n const callback = () => {\n this.logRequest(exchange);\n return this.web(exchange)\n .then(() => {\n this.logResponse(exchange);\n })\n .catch((error: Error) => {\n this.handleUnresolvedError(exchange, error)\n })\n .then(async () => {\n await exchange.response.end();\n });\n };\n\n await new Promise<void>((resolve, reject) => {\n if (this.#storage !== undefined) {\n this.#storage.run({exchange}, () => {\n callback().then(() => resolve()).catch((error) => reject(error));\n });\n } else {\n callback().then(() => resolve()).catch((error) => reject(error));\n }\n });\n }\n}\n\nexport class WebHttpHandlerBuilder {\n readonly #webHandler: WebHandler;\n readonly #middleware: Middleware = [];\n #storage?: AsyncLocalStorage<{ exchange: ServerWebExchange }> = new AsyncLocalStorage();\n #handlerDecorator?: (handler: HttpHandler) => HttpHandler;\n\n constructor(webHandler: WebHandler) {\n this.#webHandler = webHandler;\n }\n\n middleware(consumer: (middleware: Middleware) => void): this {\n consumer(this.#middleware);\n return this;\n }\n\n storage(storage: AsyncLocalStorage<{ exchange: ServerWebExchange }>): this {\n this.#storage = storage;\n return this;\n }\n\n httpHandlerDecorator(decorator: (handler: HttpHandler) => HttpHandler): this {\n if (this.#handlerDecorator === undefined) {\n this.#handlerDecorator = decorator;\n }\n else {\n const previousDecorator = this.#handlerDecorator;\n this.#handlerDecorator = (handler: HttpHandler) => {\n handler = decorator(handler);\n handler = previousDecorator(handler);\n return handler;\n }\n }\n return this;\n }\n\n hasHttpHandlerDecorator(): boolean {\n return this.#handlerDecorator !== undefined;\n }\n\n build(): HttpHandler {\n const logger = getLogger('http');\n\n const adapter = new HandlerAdapter(logger, this.#webHandler);\n if (this.#storage !== undefined) adapter.storage = this.#storage;\n adapter.enableLoggingRequestDetails = false;\n const adapted: HttpHandler = async (request, response) => adapter.http(request, response);\n\n\n return this.#handlerDecorator ? this.#handlerDecorator(adapted) : adapted;\n }\n}\n", "import type { ClientHttpConnector } from '../../client/types.js';\nimport { HttpHandler } from '../../server/types.js';\nimport { MockClientHttpRequest, MockClientHttpResponse } from '../../mock/client/exchange.ts';\nimport { MockServerHttpRequest, MockServerHttpResponse } from '../../mock/server/exchange.ts';\nimport { BodyChunk, HttpMethod } from '../../../types/web/http';\nimport type { ClientHttpRequest, ClientHttpResponse } from '../../../types/web/client';\n\nimport getLogger from '../../logger.js';\nimport type { ServerHttpRequest, ServerHttpResponse, SslInfo } from '../../../types/web/server';\nimport { HttpHeadResponseDecorator } from '../../server/handler.ts';\nimport stream from 'node:stream/web';\n\n\nclass FailureAfterResponseCompletedError extends Error {\n readonly completedResponse: ClientHttpResponse;\n\n constructor(response: ClientHttpResponse, options: { cause?: Error } = {}) {\n super(`error occurred after response was completed: ${response}`, options);\n this.completedResponse = response;\n }\n}\n\ntype Sink<T> = {\n resolve: (value: T | PromiseLike<T>) => void,\n reject: (reason?: unknown) => void,\n promise: Promise<T>\n}\n\nasync function sink<T>(): Promise<Sink<T>> {\n try {\n return await new Promise<Sink<T>>((result, _error) => {\n\n const promise = new Promise<T>((resolve, reject) => {\n Promise.resolve().then(() => {\n result({promise, resolve, reject});\n });\n });\n });\n }\n catch (error) {\n throw error;\n }\n}\n\nexport class HttpHandlerConnector implements ClientHttpConnector {\n static readonly #logger = getLogger('test.http.handler.connector');\n readonly #httpHandler: HttpHandler;\n readonly #sslInfo?: SslInfo;\n\n constructor(httpHandler: HttpHandler, sslInfo?: SslInfo) {\n this.#httpHandler = httpHandler;\n this.#sslInfo = sslInfo;\n }\n\n async connect(method: HttpMethod, uri: URL,\n requestCallback: (request: ClientHttpRequest) => Promise<void>): Promise<ClientHttpResponse> {\n\n const requestWriteSink = await sink<void>();\n const handlerSink = await sink<void>();\n const savedResponse: [ClientHttpResponse | undefined] = [undefined];\n\n const mockClientRequest = new MockClientHttpRequest(uri, method);\n const mockServerResponse = new MockServerHttpResponse();\n\n mockClientRequest.writeHandler = async (responseBody) => {\n this.log('Invoking HttpHandler for ', method, uri);\n const mockServerRequest = await this.adoptRequest(mockClientRequest, responseBody);\n const responseToUse = this.prepareResponse(mockServerResponse, mockServerRequest);\n\n try {\n await this.#httpHandler(mockServerRequest, responseToUse);\n handlerSink.resolve();\n } catch (e) {\n handlerSink.reject(e);\n }\n return true;\n\n }\n\n mockServerResponse.writeHandler = async (responseBody) => {\n this.log('Creating client response for ', method, uri);\n savedResponse[0] = this.adoptResponse(mockServerResponse, responseBody);\n return true;\n }\n this.log('Writing client request for ', method, uri);\n\n requestCallback(mockClientRequest)\n .then(() => {\n requestWriteSink.resolve();\n })\n .catch(error => {\n requestWriteSink.reject(error);\n });\n\n return Promise.all([requestWriteSink.promise, handlerSink.promise])\n .catch((error) => {\n const response = savedResponse[0];\n throw response !== undefined ? new FailureAfterResponseCompletedError(response, {cause: error}) : error;\n }).then(() => {\n const response = savedResponse[0];\n return response ?? this.adoptResponse(mockServerResponse, stream.ReadableStream.from([]) as ReadableStream<BodyChunk>);\n });\n\n }\n\n private log(message: string, method: HttpMethod, uri: URL): void {\n if (HttpHandlerConnector.#logger.enabledFor('debug')) {\n HttpHandlerConnector.#logger.debug(`${message} ${method} \"${uri.href}\"`);\n }\n }\n\n private async adoptRequest(request: MockClientHttpRequest, body: ReadableStream<BodyChunk>): Promise<ServerHttpRequest> {\n const method = request.method;\n const uri = request.URL;\n const headers = request.headers;\n const _cookies = request.cookies;\n const result = new MockServerHttpRequest(uri, method)\n for (const name of headers.keys()) {\n let value = headers.get(name);\n if (value !== undefined) {\n if (typeof value === 'number') {\n value = String(value);\n }\n if (typeof value === 'string') {\n result.setHeader(name, value);\n } else {\n for (const v of value) {\n result.addHeader(name, v);\n }\n }\n }\n }\n await result.writeBody(body)\n return result;\n }\n\n private prepareResponse(response: ServerHttpResponse, request: ServerHttpRequest): ServerHttpResponse {\n return request.method === 'HEAD' ? new HttpHeadResponseDecorator(response) : response;\n\n }\n\n private adoptResponse(response: MockServerHttpResponse, body: ReadableStream<BodyChunk>): ClientHttpResponse {\n const status = response.statusCode;\n const headers = response.headers;\n const _cookies = response.cookies;\n const result = new MockClientHttpResponse(status);\n for (const name of headers.keys()) {\n let value = headers.get(name);\n if (value !== undefined) {\n if (typeof value === 'number') {\n value = String(value);\n }\n if (typeof value === 'string') {\n result.setHeader(name, value);\n } else {\n for (const v of value) {\n result.addHeader(name, v);\n }\n }\n }\n }\n result.body = body;\n return result;\n }\n}\n\n", "import { IOGateway } from '@interopio/gateway';\nimport type { OriginFilters } from '../../types/web/server';\nimport getLogger from '../logger.ts';\n\nconst log = getLogger('gateway.ws.client-verify');\n\nexport type ProcessedOriginFilters\n = Required<Omit<OriginFilters, 'blacklist' | 'whitelist'>>\n //| Required<Omit<GatewayServer.OriginFilters, 'block' | 'allow'>>\n ;\n\nfunction acceptsMissing(originFilters: ProcessedOriginFilters): boolean {\n switch (originFilters.missing) {\n case 'allow': // fall-through\n case 'whitelist':\n return true;\n case 'block': // fall-through\n case 'blacklist':\n return false;\n default:\n return false;\n }\n}\n\nfunction tryMatch(originFilters: ProcessedOriginFilters, origin: string): boolean | undefined {\n const block = originFilters.block ?? originFilters['blacklist'];\n const allow = originFilters.allow ?? originFilters['whitelist'];\n if (block.length > 0 && IOGateway.Filtering.valuesMatch(block, origin)) {\n log.warn(`origin ${origin} matches block filter`);\n return false;\n } else if (allow.length > 0 && IOGateway.Filtering.valuesMatch(allow, origin)) {\n if (log.enabledFor('debug')) {\n log.debug(`origin ${origin} matches allow filter`);\n }\n return true;\n }\n}\n\nfunction acceptsNonMatched(originFilters: ProcessedOriginFilters): boolean {\n switch (originFilters.non_matched) {\n case 'allow': // fall-through\n case 'whitelist':\n return true;\n case 'block': // fall-through\n case 'blacklist':\n return false;\n default:\n return false;\n }\n}\n\nexport function acceptsOrigin(origin?: string, originFilters?: ProcessedOriginFilters): boolean {\n if (!originFilters) {\n return true;\n }\n if (!origin) {\n return acceptsMissing(originFilters);\n } else {\n const matchResult: boolean | undefined = tryMatch(originFilters, origin);\n if (matchResult) {\n return matchResult;\n } else {\n return acceptsNonMatched(originFilters);\n }\n }\n}\n\nexport function regexifyOriginFilters(originFilters?: OriginFilters): ProcessedOriginFilters | undefined {\n if (originFilters) {\n const block = (originFilters.block ?? originFilters.blacklist ?? []).map(IOGateway.Filtering.regexify);\n const allow = (originFilters.allow ?? originFilters.whitelist ?? []).map(IOGateway.Filtering.regexify);\n return {\n non_matched: originFilters.non_matched ?? 'allow',\n missing: originFilters.missing ?? 'allow',\n allow,\n block,\n }\n }\n}\n", "import type {ServerWebExchange} from '../../../types/web/server';\n\nexport type MatchResult = Readonly<{ match: boolean, variables: Readonly<Record<string, string>> }>;\n\nexport interface ServerWebExchangeMatcher {\n /**\n * Matches the given exchange against the matcher.\n * @param exchange The web exchange to match.\n * @returns A promise that resolves to true if the exchange matches, false otherwise.\n */\n (exchange: ServerWebExchange): Promise<MatchResult>;\n\n /**\n * Returns a string representation of the matcher.\n * @returns A string representation of the matcher.\n */\n toString(): string;\n}\n\nexport type ServerWebExchangeMatcherEntry<T> = Readonly<[ServerWebExchangeMatcher, T]>\n\nexport const or: (matchers: ServerWebExchangeMatcher[]) => ServerWebExchangeMatcher = (matchers: ServerWebExchangeMatcher[]): ServerWebExchangeMatcher => {\n return async (exchange: ServerWebExchange): Promise<MatchResult> => {\n for (const matcher of matchers) {\n const result = await matcher(exchange);\n if (result.match) {\n return match();\n }\n }\n return NO_MATCH;\n };\n}\n\nexport const and: (matchers: ServerWebExchangeMatcher[]) => ServerWebExchangeMatcher = (matchers: ServerWebExchangeMatcher[]) => {\n const matcher = async (exchange: ServerWebExchange): Promise<MatchResult> => {\n for (const matcher of matchers) {\n const result = await matcher(exchange);\n if (!result.match) {\n return NO_MATCH;\n }\n }\n return match();\n };\n matcher.toString = () => `and(${matchers.map(m => m.toString()).join(', ')})`;\n return matcher;\n}\n\n\nexport const not: (matcher: ServerWebExchangeMatcher) => ServerWebExchangeMatcher = (matcher: ServerWebExchangeMatcher): ServerWebExchangeMatcher => {\n return async (exchange: ServerWebExchange): Promise<MatchResult> => {\n const result = await matcher(exchange);\n return result.match ? NO_MATCH : match();\n };\n}\n\nexport const anyExchange: ServerWebExchangeMatcher = async (_exchange: ServerWebExchange): Promise<MatchResult> => {\n return match();\n}\nanyExchange.toString = () => 'any-exchange';\n\nconst EMPTY_OBJECT = Object.freeze({});\nexport const NO_MATCH: MatchResult = Object.freeze({match: false, variables: EMPTY_OBJECT});\nexport const match = (variables: Record<string, string> = EMPTY_OBJECT): MatchResult => {\n return { match: true, variables };\n}\n\nexport const pattern: ((pattern: string | RegExp, opts?: {method?: string}) => ServerWebExchangeMatcher) = (pattern, opts) => {\n const method = opts?.method;\n const matcher = async (exchange: ServerWebExchange): Promise<MatchResult> => {\n const request = exchange.request;\n const path = request.path;\n if (method !== undefined && request.method !== method) {\n return NO_MATCH;\n }\n if (typeof pattern === 'string') {\n if (path === pattern) {\n return match();\n }\n return NO_MATCH;\n }\n else {\n const match = pattern.exec(path);\n if (match === null) {\n return NO_MATCH;\n }\n return {match: true, variables: {...match.groups}};\n }\n };\n matcher.toString = () => {\n return `pattern(${pattern.toString()}, method=${method ?? '<any>'})`;\n }\n return matcher\n\n}\nexport const mediaType : ((opts: { mediaTypes: string[], ignoredMediaTypes?: string[], useEquality?: boolean }) => ServerWebExchangeMatcher) = (opts): ServerWebExchangeMatcher => {\n\n const shouldIgnore = (requestedMediaType: string): boolean => {\n if (opts.ignoredMediaTypes !== undefined) {\n for (const ignoredMediaType of opts.ignoredMediaTypes) {\n if (requestedMediaType === ignoredMediaType || ignoredMediaType === '*/*') {\n return true;\n }\n }\n }\n return false;\n }\n\n return async (exchange: ServerWebExchange): Promise<MatchResult> => {\n const request = exchange.request;\n let requestMediaTypes: string[];\n try {\n requestMediaTypes = request.headers.list('accept');\n }\n catch (e) {\n return NO_MATCH;\n }\n for (const requestedMediaType of requestMediaTypes) {\n if (shouldIgnore(requestedMediaType)) {\n continue;\n }\n for (const mediaType of opts.mediaTypes) {\n if (requestedMediaType.startsWith(mediaType)) {\n return match();\n }\n }\n }\n\n return NO_MATCH;\n };\n}\n\nexport const upgradeMatcher: ServerWebExchangeMatcher = async ({request}: ServerWebExchange): Promise<MatchResult> => {\n const upgrade = request.upgrade && request.headers.one('upgrade')?.toLowerCase() === 'websocket';\n return upgrade ? match() : NO_MATCH;\n};\nupgradeMatcher.toString = () => 'websocket upgrade';\n", "import { regexifyOriginFilters } from '../server/ws-client-verify.ts';\nimport type { SecurityContext } from '../server/security/security-context.ts';\nimport { pattern, type ServerWebExchangeMatcher } from '../server/util/matchers.ts';\nimport type { CorsConfig } from '../server/cors.ts';\nimport type { Middleware } from '../server/types.ts';\nimport type { AsyncLocalStorage } from 'node:async_hooks';\nimport type { SocketRoute } from '../server/socket.ts';\nimport { GatewayServer } from '@interopio/gateway-server';\nimport type {\n ServerConfigurer,\n ServerConfigurerHandlerSpec,\n ServerConfigurerSocketSpec,\n ServerExchangeOptions,\n ServerWebExchange\n} from '../../types/web/server';\nimport type { AuthorizationRule } from '../../types/auth';\nimport { IOGateway } from '@interopio/gateway';\n\nexport type PathPattern = string | RegExp;\nexport type RouteConfig = Readonly<{\n readonly storage: AsyncLocalStorage<{\n exchange: ServerWebExchange,\n securityContext?: Promise<SecurityContext>\n }>,\n readonly serverHeader?: string | false\n readonly corsConfig?: GatewayServer.ServerConfig['cors'],\n readonly authConfig?: GatewayServer.ServerConfig['auth'],\n readonly middleware: Middleware,\n readonly cors: Array<[PathPattern, CorsConfig | undefined]>,\n readonly authorize: Array<[ServerWebExchangeMatcher, AuthorizationRule]>\n readonly sockets: Map<string, SocketRoute>\n readonly resourcesConfig?: GatewayServer.ServerConfig['resources']\n}>\n\nexport async function configure(app: GatewayServer.ServerCustomizer, config: GatewayServer.ServerConfig, routes: RouteConfig): Promise<void> {\n const applyCors = (request: ServerConfigurerHandlerSpec['request'], options?: ServerExchangeOptions) => {\n // // disable CORS for this route\n // if (options?.cors === false) {\n // const path = request.path as (PathPattern);\n // routes.cors.push([request.path, undefined]);\n // }\n if (options?.cors) {\n const cors: CorsConfig = options.cors === true ? {\n allowOrigins: options.origins?.allow?.map(IOGateway.Filtering.regexify),\n allowMethods: request.method === undefined ? ['*'] : [request.method],\n allowCredentials: options.authorize?.access !== 'permitted' ? true : undefined,\n } : options.cors;\n const path = request.path as (PathPattern);\n routes.cors.push([path, cors]);\n }\n }\n\n const configurer = new class implements ServerConfigurer {\n\n handle(...handlers: Array<ServerConfigurerHandlerSpec>) {\n handlers.forEach(({request, options, handler}) => {\n const matcher = pattern(IOGateway.Filtering.regexify(request.path) as string | RegExp, {method: request.method});\n if (options?.authorize) {\n routes.authorize.push([matcher, options.authorize]);\n }\n\n applyCors(request, options);\n const middleware = async (exchange: ServerWebExchange, next: () => Promise<void>): Promise<void> => {\n const {match, variables} = await matcher(exchange);\n if (match) {\n await handler(exchange, variables);\n } else {\n await next();\n }\n };\n routes.middleware.push(middleware);\n });\n }\n\n socket(...sockets: Array<ServerConfigurerSocketSpec>) {\n for (const {path, factory, options} of sockets) {\n const route = path ?? '/';\n\n // cors and authorize are currently handled for ws\n routes.sockets.set(route, {\n default: path === undefined || path === '/',\n ping: options?.ping,\n factory: factory,\n maxConnections: options?.maxConnections,\n authorize: options?.authorize,\n originFilters: regexifyOriginFilters(options?.origins)\n });\n }\n }\n };\n await app(configurer, config);\n}\n", "type MiddlewareFunction<T> = ((ctx: T, next: (ctx?: T) => Promise<void>) => Promise<void>) | ((ctx: T) => Promise<void>);\n\n// https://github.com/koajs/compose/blob/master/index.js\n/**\n * @typeParam T - Type of context passed through the middleware\n * @param middleware middleware stack\n * @return {MiddlewareFunction}\n */\nexport function compose<T>(...middleware: MiddlewareFunction<T>[]): (ctx: T) => Promise<void> {\n if (!Array.isArray(middleware)) {\n throw new Error('middleware must be array!');\n }\n const fns = middleware.flat();\n for (const fn of fns) {\n if (typeof fn !== 'function') {\n throw new Error('middleware must be compose of functions!');\n }\n }\n return async function (ctx: T, next?: (ctx?: T) => Promise<void>) {\n const dispatch = async (i: number, dispatchedCtx: T): Promise<void> => {\n const fn = i === fns.length ? next : fns[i];\n if (fn === undefined) {\n return;\n }\n let nextCalled = false;\n let nextResolved = false;\n const nextFn = async (nextCtx?: T) => {\n if (nextCalled) {\n throw new Error('next() called multiple times');\n }\n nextCalled = true;\n try {\n return await dispatch(i + 1, nextCtx ?? dispatchedCtx);\n }\n finally {\n nextResolved = true;\n }\n };\n const result = await fn(dispatchedCtx, nextFn);\n if (nextCalled && !nextResolved) {\n throw new Error('middleware resolved before downstream.\\n\\t You are probably missing an await or return statement in your middleware function.');\n }\n return result;\n }\n\n return dispatch(0, ctx);\n }\n}\n", "import type { ClientHttpConnector } from '../../client/types.ts';\nimport { FetchClientHttpConnector } from '../../client/fetch.ts';\nimport type {\n HttpMethod\n} from '../../../types/web/http';\nimport type {\n TestClient,\n TestClientBuilder,\n MockServerSpec\n} from '../../../types/web/test';\nimport { GatewayServer } from '../../../gateway-server';\nimport { HttpHandlerConnector } from './handler.ts';\nimport { WebHttpHandlerBuilder } from '../../server/handler.ts';\nimport { configure, type RouteConfig } from '../../app/route.ts';\nimport { compose } from '../../common/compose.ts';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Middleware, ServerWebExchange, SslInfo } from '../../../types/web/server';\nimport type { SocketRoute } from '../../server/socket.ts';\n\nexport function bindToApp(app: GatewayServer.ServerCustomizer): MockServerSpec {\n return new AppSpec(app);\n}\n\nexport function bindToServer(): TestClientBuilder {\n return new DefaultTestClientBuilder();\n}\n\nclass DefaultTestClient implements TestClient {\n readonly #connector: ClientHttpConnector;\n readonly #baseUrl?: string;\n constructor(connector: ClientHttpConnector,\n baseUrl: string | undefined,\n _builder: TestClientBuilder) {\n this.#connector = connector;\n this.#baseUrl = baseUrl;\n }\n\n fetch = async (input: string | URL, init?: RequestInit): Promise<Response> => {\n try {\n const method = init?.method as HttpMethod ?? 'GET';\n const uri = new URL(input, this.#baseUrl);\n const response = await this.#connector.connect(method, uri, async (request) => {\n // fetch Request to ClientHttpRequest\n const headers = new Headers(init?.headers);\n for (const [name, value] of headers.entries()) {\n request.headers.add(name, value);\n }\n let body = init?.body ?? Promise.resolve();\n if (body instanceof ReadableStream) {\n throw new Error(`Unsupported body type ${typeof init?.body} in fetch request`);\n }\n if (body instanceof FormData) {\n // Convert FormData to URLSearchParams\n const formDataEntries = Array.from(body.entries());\n body = new URLSearchParams();\n for (const [key, value] of formDataEntries) {\n body.append(key, value.toString());\n }\n }\n if (body instanceof URLSearchParams) {\n if (!request.headers.has('content-type')) {\n request.headers.set('content-type', 'application/x-www-form-urlencoded');\n }\n body = body.toString();\n }\n if (body instanceof Blob) {\n body = await body.bytes();\n }\n if (typeof body === 'string') {\n body = Buffer.from(body);\n }\n await request.body(body);\n\n\n });\n // ClientHttpResponse to fetch Response\n const headers = new Headers();\n for (const key of response.headers.keys()) {\n const value = response.headers.get(key);\n if (value !== undefined) {\n if (typeof value === 'string') {\n headers.set(key, value);\n } else if (Array.isArray(value)) {\n for (const v of value) {\n headers.append(key, v);\n }\n }\n }\n }\n const status = response.statusCode?.value;\n const body = await response.blob();\n return new Response(body, {status, headers});\n }\n catch (error) {\n return Response.error();\n }\n\n }\n}\n\nclass DefaultTestClientBuilder implements TestClientBuilder {\n readonly #httpHandlerBuilder?: Promise<WebHttpHandlerBuilder>;\n #connector?: ClientHttpConnector;\n #sslInfo?: SslInfo;\n #baseUrl: string = 'http://localhost:8080';\n\n constructor(httpHandlerBuilder?: Promise<WebHttpHandlerBuilder>, connector?: ClientHttpConnector, sslInfo?: SslInfo) {\n if (!(httpHandlerBuilder === undefined || connector === undefined)) {\n throw new Error('You can only set either httpHandlerBuilder or connector, not both.');\n }\n this.#connector = connector;\n this.#sslInfo = sslInfo;\n this.#httpHandlerBuilder = httpHandlerBuilder;\n }\n\n baseUrl(baseUrl: string): this {\n this.#baseUrl = baseUrl;\n return this;\n }\n\n clientConnector(connector: ClientHttpConnector): this {\n this.#connector = connector;\n return this;\n }\n\n async build(): Promise<TestClient> {\n let connector = this.#connector;\n if (connector === undefined) {\n if (this.#httpHandlerBuilder !== undefined) {\n connector = new HttpHandlerConnector((await this.#httpHandlerBuilder).build(), this.#sslInfo);\n }\n }\n connector ??= new FetchClientHttpConnector();\n\n return new DefaultTestClient(connector, this.#baseUrl, this);\n }\n}\n\nabstract class AbstractMockServerSpec implements MockServerSpec {\n #sslInfo?: SslInfo;\n #middleware: Middleware = [];\n\n middleware(...middleware: Middleware): this {\n this.#middleware = [...(this.#middleware), ...middleware];\n return this;\n }\n\n sslInfo(sslInfo?: SslInfo): this {\n this.#sslInfo = sslInfo;\n return this;\n }\n\n configureClient(): TestClientBuilder {\n const builder = this.initHttpHandlerBuilder(...this.#middleware);\n\n return new DefaultTestClientBuilder(builder, undefined, this.#sslInfo);\n }\n\n protected abstract initHttpHandlerBuilder(...middleware: Middleware): Promise<WebHttpHandlerBuilder>;\n\n async build(): Promise<TestClient> {\n return await this.configureClient().build();\n }\n}\n\nclass AppSpec extends AbstractMockServerSpec {\n readonly #app: GatewayServer.ServerCustomizer;\n constructor(app: GatewayServer.ServerCustomizer) {\n super();\n this.#app = app;\n }\n\n protected async initHttpHandlerBuilder(...middleware: Middleware) {\n const routes: RouteConfig = {\n middleware,\n corsConfig: {\n allowOrigin: ['http://localhost:8086']\n },\n resourcesConfig: {\n locations: []\n },\n cors: [],\n authConfig: {type: \"none\"},\n authorize: [],\n storage: new AsyncLocalStorage<{ exchange: ServerWebExchange }>(),\n sockets: new Map<string, SocketRoute>()\n };\n\n await configure(this.#app, {}, routes);\n const handler = compose(...routes.middleware)\n return new WebHttpHandlerBuilder(handler);\n }\n}\n", "import { bindToApp, bindToServer } from './server/client.ts';\n\nexport const TestClient = {\n bindToApp: bindToApp,\n bindToServer: bindToServer\n}\n"],
5
- "mappings": "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",
6
- "names": ["isIP", "Cookie", "parseHost", "headers", "defaultHost", "host", "port", "isForwardedSsl", "v", "parseProtocol", "defaultProtocol", "proto", "parseRemoteAddress", "url", "remoteAddress", "AbstractHttpMessage", "#headers", "AbstractHttpRequest", "_AbstractHttpRequest", "#id", "parseCookies", "AbstractHttpResponse", "parseResponseCookies", "responseCookie", "parseHeader", "value", "list", "start", "end", "i", "toList", "values", "s", "cs", "tc", "cookie", "parsed", "result", "MapHttpHeaders", "name", "values", "toList", "value", "prev", "AbstractClientHttpRequest", "AbstractHttpRequest", "method", "uri", "MapHttpHeaders", "AbstractClientHttpResponse", "AbstractHttpResponse", "statusCode", "headers", "DefaultHttpStatusCode", "#value", "value", "HttpStatus", "_HttpStatus", "#VALUES", "key", "code", "status", "#phrase", "phrase", "httpStatusCode", "FetchClientHttpRequest", "AbstractClientHttpRequest", "#body", "method", "uri", "body", "headers", "key", "value", "toHttpHeaders", "result", "MapHttpHeaders", "FetchClientHttpResponse", "AbstractClientHttpResponse", "#response", "response", "httpStatusCode", "FetchClientHttpConnector", "#fetch", "fetchFn", "requestCallback", "fetchClientHttpRequest", "fetchRequest", "fetchResponse", "stream", "MockClientHttpRequest", "AbstractClientHttpRequest", "#writeHandler", "#body", "uri", "method", "body", "chunks", "reader", "done", "value", "doneReading", "handler", "asyncIterator", "MockClientHttpResponse", "AbstractHttpResponse", "#statusCode", "status", "MapHttpHeaders", "httpStatusCode", "name", "charset", "chunk", "stream", "http", "ExtendedHttpIncomingMessage", "ExtendedHttpServerResponse", "AbstractServerHttpResponse", "AbstractHttpResponse", "#cookies", "#statusCode", "#state", "#commitActions", "statusCode", "httpStatusCode", "cookie", "action", "state", "body", "buffer", "error", "writeAction", "allActions", "acc", "cur", "_error", "ServerHttpResponseDecorator", "_ServerHttpResponseDecorator", "#delegate", "response", "statusCode", "cookie", "body", "AbstractServerHttpResponse", "DefaultWebExchange", "#attributes", "#logId", "#logPrefix", "request", "response", "LOG_ID_ATTRIBUTE", "name", "value", "MockServerHttpRequest", "AbstractHttpRequest", "#url", "#body", "url", "method", "MapHttpHeaders", "blob", "asyncIterator", "stream", "body", "text", "chunks", "reader", "done", "value", "readDone", "name", "MockServerHttpResponse", "AbstractServerHttpResponse", "#writeHandler", "bodyStream", "handler", "cookie", "it", "resolved", "GatewayLogging", "getLogger", "name", "AsyncLocalStorage", "HttpHeadResponseDecorator", "ServerHttpResponseDecorator", "checkAndLogClientDisconnectedError", "error", "logger", "code", "message", "HandlerAdapter", "#logger", "#enableLoggingRequestDetails", "#delegate", "#storage", "delegate", "request", "response", "DefaultWebExchange", "storage", "value", "headers", "result", "key", "query", "exchange", "trace", "status", "logPrefix", "HttpStatus", "callback", "resolve", "reject", "WebHttpHandlerBuilder", "#webHandler", "#middleware", "AsyncLocalStorage", "#handlerDecorator", "webHandler", "consumer", "decorator", "previousDecorator", "handler", "getLogger", "adapter", "adapted", "stream", "FailureAfterResponseCompletedError", "response", "options", "sink", "result", "_error", "promise", "resolve", "reject", "error", "HttpHandlerConnector", "_HttpHandlerConnector", "#logger", "getLogger", "#httpHandler", "#sslInfo", "httpHandler", "sslInfo", "method", "uri", "requestCallback", "requestWriteSink", "handlerSink", "savedResponse", "mockClientRequest", "MockClientHttpRequest", "mockServerResponse", "MockServerHttpResponse", "responseBody", "mockServerRequest", "responseToUse", "e", "message", "request", "body", "headers", "_cookies", "MockServerHttpRequest", "name", "value", "v", "HttpHeadResponseDecorator", "status", "MockClientHttpResponse", "IOGateway", "log", "getLogger", "regexifyOriginFilters", "originFilters", "block", "IOGateway", "allow", "anyExchange", "_exchange", "match", "EMPTY_OBJECT", "NO_MATCH", "variables", "pattern", "opts", "method", "matcher", "exchange", "request", "path", "upgradeMatcher", "request", "match", "NO_MATCH", "IOGateway", "configure", "app", "config", "routes", "applyCors", "request", "options", "cors", "path", "configurer", "handlers", "handler", "matcher", "pattern", "middleware", "exchange", "next", "match", "variables", "sockets", "factory", "route", "regexifyOriginFilters", "compose", "middleware", "fns", "fn", "ctx", "next", "dispatch", "i", "dispatchedCtx", "nextCalled", "nextResolved", "result", "nextCtx", "AsyncLocalStorage", "bindToApp", "app", "AppSpec", "bindToServer", "DefaultTestClientBuilder", "DefaultTestClient", "#connector", "#baseUrl", "connector", "baseUrl", "_builder", "input", "init", "method", "uri", "response", "request", "headers", "name", "value", "body", "formDataEntries", "key", "v", "status", "#httpHandlerBuilder", "#sslInfo", "httpHandlerBuilder", "sslInfo", "HttpHandlerConnector", "FetchClientHttpConnector", "AbstractMockServerSpec", "#middleware", "middleware", "builder", "#app", "routes", "configure", "handler", "compose", "WebHttpHandlerBuilder", "TestClient", "bindToApp", "bindToServer"]
3
+ "sources": ["../../src/http/exchange.ts", "../../src/http/media-type.ts", "../../src/utils/mime-type-utils.ts", "../../src/http/headers.ts", "../../src/client/exchange.ts", "../../src/http/status.ts", "../../src/client/fetch.ts", "../../src/mock/client/exchange.ts", "../../src/server/exchange.ts", "../../src/http/server/path.ts", "../../src/http/server/exchange.ts", "../../src/logger.ts", "../../src/codec/hints.ts", "../../src/codec/encoder.ts", "../../src/http/codec/core.ts", "../../src/http/codec/multipart.ts", "../../src/http/codec/config.ts", "../../src/mock/server/exchange.ts", "../../src/server/handler.ts", "../../src/test/server/handler.ts", "../../src/server/ws-client-verify.ts", "../../src/server/util/matchers.ts", "../../src/app/route.ts", "../../src/common/compose.ts", "../../src/test/server/client.ts", "../../src/web/server/adapter.ts", "../../src/web/util/client.ts", "../../src/web/server/handler.ts", "../../src/test/index.ts"],
4
+ "sourcesContent": ["import type { HttpCookie, HttpHeaders, ResponseCookie } from '../../types/web/http';\nimport { type AddressInfo, isIP } from 'node:net';\nimport { Cookie } from 'tough-cookie';\n\nfunction parseHost(headers: HttpHeaders, defaultHost?: string): string | undefined {\n let host = headers.get('x-forwarded-host');\n if (Array.isArray(host)) {\n host = host[0];\n }\n if (host) {\n const port = headers.one('x-forwarded-port');\n if (port) {\n host = `${host}:${port}`;\n }\n }\n host ??= headers.one('host');\n if (Array.isArray(host)) {\n host = host[0];\n }\n if (host) {\n return (host as string).split(',', 1)[0].trim();\n }\n\n return defaultHost;\n}\n\nfunction isForwardedSsl(headers: HttpHeaders): boolean {\n const v = headers.one('x-forwarded-ssl');\n return (typeof v === 'string') && (v.toLowerCase() === 'on');\n}\n\nfunction parseProtocol(headers: HttpHeaders, defaultProtocol: string): string {\n let proto = headers.get('x-forwarded-proto');\n\n if (Array.isArray(proto)) {\n proto = proto[0];\n }\n if (proto !== undefined) {\n return (proto as string).split(',', 1)[0].trim();\n }\n else if (isForwardedSsl(headers)) {\n return 'https';\n }\n return defaultProtocol;\n}\n\nfunction parseRemoteAddress(url: URL, headers: HttpHeaders, remoteAddress?: AddressInfo) : AddressInfo | undefined {\n const port = remoteAddress ? remoteAddress.port : 'https:' === url.protocol ? 443 : 80;\n\n let host = headers.one('x-forwarded-for');\n if (Array.isArray(host)) {\n host = host[0];\n }\n if (host !== undefined) {\n host = (host as string).split(',', 1)[0].trim();\n return { address: host, port: Number(port), family: isIP(host) === 6 ? 'IPv6' : 'IPv4' };\n }\n}\n\nexport abstract class AbstractHttpMessage<Headers extends HttpHeaders = HttpHeaders> {\n readonly #headers: Headers;\n protected constructor(headers: Headers) {\n this.#headers = headers;\n }\n get headers(): Headers {\n return this.#headers;\n }\n}\n\nexport abstract class AbstractHttpRequest<Headers extends HttpHeaders = HttpHeaders> extends AbstractHttpMessage<Headers> {\n private static logIdCounter = 0;\n #id?: string\n\n get id(): string {\n if (this.#id === undefined) {\n this.#id = `${this.initId()}-${++AbstractHttpRequest.logIdCounter}`;\n\n }\n return this.#id;\n }\n\n protected initId(): string {\n return 'request';\n }\n\n get cookies(): HttpCookie[] {\n return parseCookies(this.headers);\n }\n\n protected parseHost(defaultHost?: string): string | undefined {\n return parseHost(this.headers, defaultHost);\n }\n\n protected parseProtocol(defaultProtocol: string): string {\n return parseProtocol(this.headers, defaultProtocol);\n }\n\n abstract get URL(): URL;\n\n protected parseRemoteAddress(remoteAddress?: AddressInfo) {\n return parseRemoteAddress(this.URL, this.headers, remoteAddress);\n }\n}\n\nexport abstract class AbstractHttpResponse<Headers extends HttpHeaders = HttpHeaders> extends AbstractHttpMessage<Headers> {\n get cookies(): ResponseCookie[] {\n return parseResponseCookies(this.headers);\n }\n\n protected setCookieValue(responseCookie: ResponseCookie): string {\n const cookie = new Cookie({\n key: responseCookie.name,\n value: responseCookie.value,\n maxAge: responseCookie.maxAge,\n domain: responseCookie.domain,\n path: responseCookie.path,\n secure: responseCookie.secure,\n httpOnly: responseCookie.httpOnly,\n sameSite: responseCookie.sameSite\n });\n return cookie.toString();\n }\n\n}\n\nfunction parseCookies(headers: HttpHeaders): HttpCookie[] {\n return headers.list('cookie')\n .map(s => s.split(';').map((cs) => Cookie.parse(cs)))\n .flat(1)\n .filter((tc) => tc !== undefined)\n .map((tc) => {\n const result: HttpCookie = Object.freeze({name: tc.key, value: tc.value});\n return result;\n });\n}\n\ntype Mutable<T> = {-readonly [K in keyof T]: T[K]};\n\nfunction parseResponseCookies(headers: HttpHeaders): ResponseCookie[] {\n return headers.list('set-cookie').map((cookie) => {\n const parsed = Cookie.parse(cookie);\n if (parsed) {\n const result: Mutable<ResponseCookie> = {name: parsed.key, value: parsed.value, maxAge: Number(parsed.maxAge ?? -1)};\n if (parsed.httpOnly) result.httpOnly = true;\n if (parsed.domain) result.domain = parsed.domain;\n if (parsed.path) result.path = parsed.path;\n if (parsed.secure) result.secure = true;\n if (parsed.httpOnly) result.httpOnly = true;\n if (parsed.sameSite) result.sameSite = parsed.sameSite as 'strict' | 'lax' | 'none';\n return Object.freeze(result);\n }\n }).filter((cookie): cookie is ResponseCookie => cookie !== undefined);\n}\n", "import { extname } from 'node:path';\nimport { MIMEType } from 'node:util';\nimport {\n APPLICATION_OCTET_STREAM_VALUE, InvalidMimeTypeError,\n isWildcardSubtype,\n isWildcardType\n} from '../utils/mime-type-utils.ts';\n\n//excerpt from mime types database\nconst mimeTypes = `\napplication/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy\napplication/json json\napplication/wasm wasm\napplication/x-pkcs12 p12 pfx\ntext/css css\ntext/csv csv\ntext/html html htm\ntext/javascript js mjs\ntext/plain txt text conf def list log in\n`\n\nexport class MediaType extends MIMEType {\n static readonly ALL: MediaType = new MediaType('*/*');\n static readonly APPLICATION_OCTET_STREAM: MediaType = new MediaType(APPLICATION_OCTET_STREAM_VALUE);\n static readonly APPLICATION_JSON: MediaType = new MediaType('application/json');\n static readonly APPLICATION_NDJSON: MediaType = new MediaType('application/x-ndjson');\n\n static readonly MULTIPART_FORM_DATA: MediaType = new MediaType('multipart/form-data');\n\n static readonly TEXT_PLAIN: MediaType = new MediaType('text/plain');\n static readonly TEXT_HTML: MediaType = new MediaType('text/html');\n\n static readonly #PARAM_QUALITY_FACTOR = 'q';\n\n private constructor(input: string) {\n super(input);\n this.#checkToken(this.type);\n this.#checkToken(this.subtype);\n for (const [key, value] of this.params) {\n this.checkParameters(key, value);\n }\n }\n\n protected checkParameters(key: string, value: string) {\n this.#checkToken(key);\n if (!isQuoted(value)) {\n this.#checkToken(value);\n }\n if (key === MediaType.#PARAM_QUALITY_FACTOR) {\n const unquotedValue = unquote(value);\n const q = parseFloat(unquotedValue);\n if (isNaN(q) || q < 0.0 || q > 1.0) {\n throw new InvalidMediaTypeError(`Invalid quality value: ${value}`);\n }\n }\n }\n\n #checkToken(token: string) {\n for (let i = 0; i < token.length; i++) {\n const c = token.charCodeAt(i);\n if (c < 0x20 // control characters\n || c > 0x7E // non-ASCII characters\n || c === 0x28 // (\n || c === 0x29 // )\n || c === 0x3C // <\n || c === 0x3E // >\n || c === 0x40 // @\n || c === 0x2C // ,\n || c === 0x3B // ;\n || c === 0x3A // :\n || c === 0x5C // \\\n || c === 0x22 // \"\n || c === 0x35 // /\n || c === 0x5B // [\n || c === 0x5D // ]\n || c === 0x3F // ?\n || c === 0x3D // =\n || c === 0x7B // {\n || c === 0x7D // }\n || c === 0x20 // space\n || c === 0x09 // tab\n ) {\n throw new InvalidMediaTypeError(`Invalid token: ${token}`);\n }\n }\n }\n\n\n get quality(): number {\n const qualityFactor = this.params.get(MediaType.#PARAM_QUALITY_FACTOR);\n return (qualityFactor !== null) ? parseFloat(unquote(qualityFactor)) : 1.0;\n }\n\n static parseMediaType(input: string): MediaType {\n return new MediaType(input);\n }\n\n static parseMediaTypesList(mediaTypes: string): MediaType[] {\n if (!mediaTypes?.trim()) {\n return [];\n }\n return mediaTypes.split(',')\n .map(type => type.trim())\n .filter(type => type.length > 0)\n .map(type => MediaType.parseMediaType(type));\n }\n\n static parseMediaTypes(...mediaTypes: string[]): MediaType[] {\n if (!mediaTypes) {\n return [];\n }\n else if (mediaTypes.length === 1) {\n return MediaType.parseMediaTypesList(mediaTypes[0]);\n }\n else {\n return mediaTypes.flatMap(mediaType => MediaType.parseMediaTypesList(mediaType));\n }\n }\n\n static asMediaType(mimeType: MIMEType): MediaType {\n if (mimeType instanceof MediaType) {\n return mimeType;\n }\n return new MediaType(mimeType.toString());\n }\n\n static asMediaTypes(...mimeTypes: MIMEType[]): MediaType[] {\n return mimeTypes.map(mimeType => MediaType.asMediaType(mimeType));\n }\n}\n\nexport class InvalidMediaTypeError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\nconst fileExtensionToMediaTypes: Map<string, MediaType[]> = (function parseMimeTypes(): Map<string, MediaType[]> {\n const map = new Map<string, MediaType[]>();\n\n for (const line of mimeTypes.trim().split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n\n const parts = trimmed.split(/\\s+/);\n if (parts.length < 2) continue;\n\n const [mimeType, ...extensions] = parts;\n const mediaType = MediaType.parseMediaType(mimeType);\n\n for (const ext of extensions) {\n const key = '.' + ext.toLowerCase();\n const existing = map.get(key);\n if (existing) {\n existing.push(mediaType);\n }\n else {\n map.set(key, [mediaType]);\n }\n }\n }\n\n return map;\n})();\n\nexport function getMediaType(filename?: string): MediaType | undefined {\n return getMediaTypes(filename)[0];\n}\n\nexport function getMediaTypes(filename?: string): MediaType[] {\n const extension = filename ? extname(filename) : '';\n let mediaTypes: MediaType[] | undefined = undefined;\n if (extension) {\n mediaTypes = fileExtensionToMediaTypes.get(extension.toLowerCase());\n }\n return mediaTypes ?? [];\n}\n\nfunction isQuoted(s: string): boolean {\n return s.length >= 2 && (\n (s.startsWith('\"') && s.endsWith('\"')) ||\n (s.startsWith(\"'\") && s.endsWith(\"'\")));\n}\n\nfunction unquote(s: string) {\n if (isQuoted(s)) {\n return s.substring(1, s.length - 1);\n }\n return s;\n}\n\nfunction isMoreSpecific(a: MIMEType, b: MIMEType): boolean {\n if (a instanceof MediaType) {\n if (b instanceof MediaType) {\n const aQuality = a.quality;\n const bQuality = b.quality;\n if (aQuality > bQuality) {\n return true;\n }\n else if (aQuality < bQuality) {\n return false;\n }\n }\n }\n const aWildcard = isWildcardType(a);\n const bWildcard = isWildcardType(b);\n if (aWildcard && !bWildcard) { // */* > text/*\n return false;\n }\n else if (!aWildcard && bWildcard) { // text/* < */*\n return true;\n }\n else {\n const aWildcardSubtype = isWildcardSubtype(a);\n const bWildcardSubtype = isWildcardSubtype(b);\n if (aWildcardSubtype && !bWildcardSubtype) { // text/* > text/html\n return false;\n }\n else if (!aWildcardSubtype && bWildcardSubtype) { // text/html < text/*\n return true;\n }\n else if (a.type === b.type && a.subtype === b.subtype) {\n const aParamsSize = Array.from(a.params.keys()).length;\n const bParamsSize = Array.from(b.params.keys()).length;\n return aParamsSize > bParamsSize; // text/html;level=1 > text/html\n }\n else {\n return false; // both are equally specific\n }\n }\n}\n\nfunction isLessSpecific(a: MIMEType, b: MIMEType): boolean {\n return isMoreSpecific(b, a);\n}\n\nfunction bubbleSort<T>(list: T[], swap: (a: T, b: T) => boolean) {\n const n = list.length;\n for (let i = 0; i < n; i++) {\n for (let j = 1; j < n - i; j++) {\n const prev = list[j - 1];\n const curr = list[j];\n if (swap(prev, curr)) {\n list[j] = prev;\n list[j - 1] = curr;\n }\n }\n }\n}\n\nexport function sortBySpecificity<T extends MIMEType>(mimeTypes: T[]) {\n if (mimeTypes === undefined) {\n throw new Error('mimeTypes must not be undefined');\n }\n if (mimeTypes.length > 100) {\n throw new InvalidMimeTypeError(`too many elements`);\n }\n bubbleSort(mimeTypes, isLessSpecific);\n\n}\n", "import { MIMEType } from 'node:util';\n\nexport const WILDCARD_TYPE = '*';\nexport const ALL = new MIMEType(`${WILDCARD_TYPE}/${WILDCARD_TYPE}`);\nexport const APPLICATION_OCTET_STREAM_VALUE = 'application/octet-stream';\nexport const APPLICATION_OCTET_STREAM = new MIMEType(APPLICATION_OCTET_STREAM_VALUE);\n\nexport function isWildcardType(mimeType: MIMEType): boolean {\n return mimeType.type === WILDCARD_TYPE;\n}\n\nexport function isWildcardSubtype(mimeType: MIMEType): boolean {\n return mimeType.subtype === WILDCARD_TYPE || mimeType.subtype.startsWith(`${WILDCARD_TYPE}+`);\n}\n\nexport function isConcrete(mimeType: MIMEType): boolean {\n return !isWildcardType(mimeType) && !isWildcardSubtype(mimeType);\n}\n\n\nexport class InvalidMimeTypeError extends Error {\n readonly mimeType: string;\n constructor(mimeType: string, message?: string, options?: ErrorOptions) {\n super(message === undefined ? `Invalid MIME type \"${mimeType}\"` : `Invalid MIME type \"${mimeType}\": ${message}`, options);\n this.mimeType = mimeType;\n }\n}\n\nexport function createMimeType(type: string, subtype: string, charset?: string): MIMEType {\n const input = `${type}/${subtype}`;\n let result: MIMEType;\n try {\n result = new MIMEType(input);\n }\n catch (error) {\n throw new InvalidMimeTypeError(input, undefined, { cause: error } );\n }\n if (charset) {\n result.params.set('charset', charset);\n }\n return result;\n}\n\nexport function getSubtypeSuffix(mimeType: MIMEType): string | null {\n const suffixIndex = mimeType.subtype.lastIndexOf('+');\n if (suffixIndex !== -1 && suffixIndex < mimeType.subtype.length) {\n return mimeType.subtype.substring(suffixIndex + 1);\n }\n return null;\n\n}\n\nexport function isCompatibleWith(a: MIMEType, b?: MIMEType): boolean {\n if (!b) {\n return false;\n }\n\n if (isWildcardType(a) || isWildcardType(b)) {\n return true;\n }\n\n else if (a.type === b.type) {\n if (a.subtype === b.subtype) {\n return true;\n }\n if (isWildcardSubtype(a) || isWildcardSubtype(b)) {\n const aSuffix = getSubtypeSuffix(a);\n const bSuffix = getSubtypeSuffix(b);\n if (a.subtype === WILDCARD_TYPE || b.subtype === WILDCARD_TYPE) {\n return true;\n }\n else if (isWildcardSubtype(a) && bSuffix !== null) {\n return aSuffix === b.subtype || aSuffix === bSuffix;\n }\n else if (isWildcardSubtype(b) && aSuffix !== null) {\n return a.subtype === bSuffix || bSuffix === aSuffix;\n }\n }\n }\n return false;\n}\n", "import type {\n HeaderValues,\n HttpHeaders,\n MutableHttpHeaders,\n ReadonlyHeaderValues, ReadonlyHttpHeaders\n} from '../../types/web/http';\nimport { MediaType } from './media-type.ts';\n\nfunction parseHeader(value: string): string[] {\n const list: string[] = [];\n {\n let start = 0;\n let end = 0;\n\n for (let i = 0; i < value.length; i++) {\n switch (value.charCodeAt(i)) {\n case 0x20: // space\n if (start === end) {\n start = end = i + 1;\n }\n break;\n case 0x2c: // comma\n list.push(value.slice(start, end));\n start = end = i + 1;\n break;\n default:\n end = end + 1;\n break;\n }\n }\n list.push(value.slice(start, end));\n }\n\n return list;\n}\n\nfunction toList(values: number | string | (readonly string[]) | undefined): string[] {\n if (typeof values === 'string') {\n values = [values];\n }\n if (typeof values === 'number') {\n values = [String(values)];\n }\n const list: string[] = [];\n if (values) {\n for (const value of values) {\n if (value) {\n list.push(...parseHeader(value));\n }\n }\n }\n return list;\n}\n\nexport abstract class AbstractHttpHeaders<Values extends HeaderValues | ReadonlyHeaderValues> {\n protected constructor() {\n }\n\n abstract get(name: string): Values\n\n toList(name: string): string[] {\n const values = this.get(name);\n return toList(values);\n }\n}\n\nexport class MapHttpHeaders extends Map<string, (readonly string[])> implements MutableHttpHeaders {\n\n get(name: string) {\n return super.get(name.toLowerCase());\n }\n\n one(name: string): string | undefined {\n return this.get(name)?.[0];\n }\n\n list(name: string) {\n const values = super.get(name.toLowerCase());\n return toList(values);\n }\n\n set(name: string, value: number | string | (readonly string[]) | undefined): this {\n if (typeof value === 'number') {\n value = String(value);\n }\n if (typeof value === 'string') {\n value = [value];\n }\n if (value) {\n return super.set(name.toLowerCase(), value);\n }\n else {\n super.delete(name.toLowerCase());\n return this;\n }\n }\n\n add(name: string, value: string | (readonly string[])) {\n const prev = super.get(name.toLowerCase());\n if (typeof value === 'string') {\n value = [value];\n }\n if (prev) {\n value = prev.concat(value);\n }\n this.set(name, value);\n return this;\n }\n}\n\nexport const EMPTY_HTTP_HEADERS: ReadonlyHttpHeaders = new MapHttpHeaders();\n\n\nexport function getContentType(headers: HttpHeaders): MediaType | undefined {\n const value = headers.one('content-type');\n return value ? MediaType.parseMediaType(value as string) : undefined;\n\n}\n", "import type {\n HttpMethod,\n HttpStatusCode,\n MutableHttpHeaders,\n ReadonlyHttpHeaders\n} from '../../types/web/http';\n\nimport { AbstractHttpRequest, AbstractHttpResponse } from '../http/exchange.ts';\nimport { MapHttpHeaders } from '../http/headers.ts';\n\nexport abstract class AbstractClientHttpRequest extends AbstractHttpRequest<MutableHttpHeaders> {\n\n protected constructor(method: HttpMethod, uri: URL) {\n super(new MapHttpHeaders());\n this.URL = uri;\n this.method = method;\n }\n\n readonly URL: URL;\n readonly method: HttpMethod;\n}\n\nexport abstract class AbstractClientHttpResponse extends AbstractHttpResponse<ReadonlyHttpHeaders> {\n protected constructor(statusCode: HttpStatusCode, headers: ReadonlyHttpHeaders) {\n super(headers);\n this.statusCode = statusCode;\n }\n readonly statusCode: HttpStatusCode;\n}\n", "import type {HttpStatusCode} from '../../types/web/http';\n\nclass DefaultHttpStatusCode implements HttpStatusCode {\n readonly #value: number;\n constructor(value: number) {\n this.#value = value;\n }\n get value(): number {\n return this.#value;\n }\n\n toString(): string {\n return this.#value.toString();\n }\n}\n\nexport class HttpStatus implements HttpStatusCode {\n static readonly CONTINUE = new HttpStatus(100, 'Continue');\n static readonly SWITCHING_PROTOCOLS = new HttpStatus(101, 'Switching Protocols');\n\n // 2xx Success\n\n static readonly OK = new HttpStatus(200, 'OK');\n static readonly CREATED = new HttpStatus(201, 'Created');\n static readonly ACCEPTED = new HttpStatus(202, 'Accepted');\n static readonly NON_AUTHORITATIVE_INFORMATION = new HttpStatus(203, 'Non-Authoritative Information');\n static readonly NO_CONTENT = new HttpStatus(204, 'No Content');\n static readonly RESET_CONTENT = new HttpStatus(205, 'Reset Content');\n static readonly PARTIAL_CONTENT = new HttpStatus(206, 'Partial Content');\n static readonly MULTI_STATUS = new HttpStatus(207, 'Multi-Status');\n\n static readonly IM_USED = new HttpStatus(226, 'IM Used');\n\n\n // 3xx Redirection\n static readonly MULTIPLE_CHOICES = new HttpStatus(300, 'Multiple Choices');\n static readonly MOVED_PERMANENTLY = new HttpStatus(301, 'Moved Permanently');\n\n // 4xx Client Error\n\n static readonly BAD_REQUEST = new HttpStatus(400, 'Bad Request');\n static readonly UNAUTHORIZED = new HttpStatus(401, 'Unauthorized');\n static readonly FORBIDDEN = new HttpStatus(403, 'Forbidden');\n static readonly NOT_FOUND = new HttpStatus(404, 'Not Found');\n static readonly METHOD_NOT_ALLOWED = new HttpStatus(405, 'Method Not Allowed');\n static readonly NOT_ACCEPTABLE = new HttpStatus(406, 'Not Acceptable');\n static readonly PROXY_AUTHENTICATION_REQUIRED = new HttpStatus(407, 'Proxy Authentication Required');\n static readonly REQUEST_TIMEOUT = new HttpStatus(408, 'Request Timeout');\n static readonly CONFLICT = new HttpStatus(409, 'Conflict');\n static readonly GONE = new HttpStatus(410, 'Gone');\n static readonly LENGTH_REQUIRED = new HttpStatus(411, 'Length Required');\n static readonly PRECONDITION_FAILED = new HttpStatus(412, 'Precondition Failed');\n static readonly PAYLOAD_TOO_LARGE = new HttpStatus(413, 'Payload Too Large');\n static readonly URI_TOO_LONG = new HttpStatus(414, 'URI Too Long');\n static readonly UNSUPPORTED_MEDIA_TYPE = new HttpStatus(415, 'Unsupported Media Type');\n\n static readonly EXPECTATION_FAILED = new HttpStatus(417, 'Expectation Failed');\n static readonly IM_A_TEAPOT = new HttpStatus(418, 'I\\'m a teapot');\n\n static readonly TOO_EARLY = new HttpStatus(425, 'Too Early');\n static readonly UPGRADE_REQUIRED = new HttpStatus(426, 'Upgrade Required');\n static readonly PRECONDITION_REQUIRED = new HttpStatus(428, 'Precondition Required');\n static readonly TOO_MANY_REQUESTS = new HttpStatus(429, 'Too Many Requests');\n static readonly REQUEST_HEADER_FIELDS_TOO_LARGE = new HttpStatus(431, 'Request Header Fields Too Large');\n static readonly UNAVAILABLE_FOR_LEGAL_REASONS = new HttpStatus(451, 'Unavailable For Legal Reasons');\n\n // 5xx Server Error\n static readonly INTERNAL_SERVER_ERROR = new HttpStatus(500, 'Internal Server Error');\n static readonly NOT_IMPLEMENTED = new HttpStatus(501, 'Not Implemented');\n static readonly BAD_GATEWAY = new HttpStatus(502, 'Bad Gateway');\n static readonly SERVICE_UNAVAILABLE = new HttpStatus(503, 'Service Unavailable');\n static readonly GATEWAY_TIMEOUT = new HttpStatus(504, 'Gateway Timeout');\n static readonly HTTP_VERSION_NOT_SUPPORTED = new HttpStatus(505, 'HTTP Version Not Supported');\n static readonly VARIANT_ALSO_NEGOTIATES = new HttpStatus(506, 'Variant Also Negotiates');\n static readonly INSUFFICIENT_STORAGE = new HttpStatus(507, 'Insufficient Storage');\n static readonly LOOP_DETECTED = new HttpStatus(508, 'Loop Detected');\n static readonly NOT_EXTENDED = new HttpStatus(510, 'Not Extended');\n static readonly NETWORK_AUTHENTICATION_REQUIRED = new HttpStatus(511, 'Network Authentication Required');\n\n static readonly #VALUES: HttpStatus[] = [];\n static {\n Object.keys(HttpStatus)\n .filter(key => key !== 'VALUES' && key !== 'resolve')\n .forEach(key => {\n const value = HttpStatus[key];\n if (value instanceof HttpStatus) {\n Object.defineProperty(value, 'name', { enumerable: true, value: key, writable: false });\n HttpStatus.#VALUES.push(value);\n }\n })\n\n }\n\n static resolve(code: number): HttpStatus | undefined {\n for (const status of HttpStatus.#VALUES) {\n if (status.value === code) {\n return status;\n }\n }\n }\n\n readonly #value: number;\n readonly #phrase: string;\n\n private constructor(value: number, phrase: string) {\n this.#value = value;\n this.#phrase = phrase;\n }\n\n get value(): number {\n return this.#value;\n }\n get phrase(): string {\n return this.#phrase;\n }\n\n toString() {\n return `${this.#value} ${this['name']}`;\n }\n}\n\n\nexport function httpStatusCode(value: number | HttpStatusCode): HttpStatusCode {\n if (typeof value === 'number') {\n if (value < 100 || value > 999) {\n throw new Error(`status code ${value} should be in range 100-999`);\n }\n const status = HttpStatus.resolve(value);\n if (status !== undefined) {\n return status;\n }\n return new DefaultHttpStatusCode(value);\n }\n return value;\n}\n", "import type {\n HttpMethod,\n BodyChunk\n} from '../../types/web/http';\nimport type {\n ClientHttpRequest,\n ClientHttpResponse\n} from '../../types/web/client';\n\nimport type { ClientHttpConnector } from './types.ts';\nimport { AbstractClientHttpRequest, AbstractClientHttpResponse } from './exchange.ts';\nimport { MapHttpHeaders } from '../http/headers.ts';\nimport { httpStatusCode } from '../http/status.ts';\n\nclass FetchClientHttpRequest extends AbstractClientHttpRequest implements ClientHttpRequest {\n #body?: BodyInit;\n constructor(method: HttpMethod, uri: URL) {\n super(method, uri);\n }\n\n async body(body: ReadableStream<BodyChunk> | Promise<BodyChunk> | BodyChunk): Promise<boolean> {\n this.#body = body instanceof ReadableStream ? body : await body;\n return await this.end();\n }\n\n end() {\n return Promise.resolve(true);\n }\n\n getNativeRequest<T>(): T {\n const method = this.method;\n const headers = new Headers();\n for (const key of this.headers.keys()) {\n if (key.toLowerCase() === 'content-length') {\n continue; // Content-Length is set automatically later\n }\n for (const value of this.headers.list(key)) {\n headers.append(key, value);\n }\n }\n if (!this.headers.has('accept')) {\n headers.append('accept', '*/*');\n }\n const body = this.#body;\n\n return new Request(this.URL, {method, headers, body}) as T;\n }\n}\nfunction toHttpHeaders(headers: Headers): MapHttpHeaders {\n const result = new MapHttpHeaders();\n for (const [key, value] of headers.entries()) {\n result.add(key, value);\n }\n return result;\n}\nclass FetchClientHttpResponse extends AbstractClientHttpResponse implements ClientHttpResponse {\n #response: Response;\n constructor(response: Response) {\n super(httpStatusCode(response.status), toHttpHeaders(response.headers));\n this.#response = response;\n }\n\n get statusMessage() {\n return this.#response.statusText;\n }\n\n get body() {\n return this.#response.body ?? undefined;\n }\n\n blob() {\n return this.#response.blob();\n }\n}\n\nexport class FetchClientHttpConnector implements ClientHttpConnector {\n readonly #fetch: typeof fetch;\n constructor(fetchFn: typeof fetch = globalThis.fetch) {\n this.#fetch = fetchFn;\n }\n\n async connect(method: HttpMethod, uri: URL, requestCallback: (request: ClientHttpRequest) => Promise<void>): Promise<ClientHttpResponse> {\n const fetchClientHttpRequest = new FetchClientHttpRequest(method, uri);\n await requestCallback(fetchClientHttpRequest);\n const fetchRequest = fetchClientHttpRequest.getNativeRequest<Request>();\n const fetchResponse = await this.#fetch(fetchRequest);\n return new FetchClientHttpResponse(fetchResponse);\n }\n}\n", "import {\n BodyChunk,\n HttpMethod,\n HttpStatusCode,\n type MutableHttpHeaders, type ReadonlyHeaderValue,\n ReadonlyHttpHeaders\n} from '../../../types/web/http';\nimport { ClientHttpRequest, ClientHttpResponse } from '../../../types/web/client';\n\nimport { AbstractClientHttpRequest } from '../../client/exchange.ts';\nimport { AbstractHttpResponse } from '../../http/exchange.ts';\nimport { MapHttpHeaders } from '../../http/headers.ts';\nimport { httpStatusCode } from '../../http/status.ts';\nimport * as stream from 'node:stream/web';\n\nexport class MockClientHttpRequest extends AbstractClientHttpRequest implements ClientHttpRequest {\n #writeHandler: (body: ReadableStream<BodyChunk>) => Promise<boolean>;\n #body: () => ReadableStream<BodyChunk> = () => {\n throw new Error(\"Body not set\");\n };\n constructor(uri: URL, method: HttpMethod) {\n super(method, uri);\n this.#writeHandler = async (body) => {\n const chunks: BodyChunk[] = [];\n this.#body = () => {\n return stream.ReadableStream.from(chunks) as ReadableStream<BodyChunk>;\n };\n const reader = body.getReader();\n let done: boolean;\n do {\n const {value, done: doneReading} = await reader.read();\n done = doneReading;\n if (value !== undefined) {\n chunks.push(value);\n }\n } while (!done);\n return true;\n }\n }\n set writeHandler(handler: (body: ReadableStream<BodyChunk>) => Promise<boolean>) {\n this.#writeHandler = handler;\n }\n\n getNativeRequest<T>(): T {\n return this as unknown as T;\n }\n\n getBody(): ReadableStream<BodyChunk> {\n return this.#body();\n }\n\n body(body: ReadableStream<BodyChunk> | Promise<BodyChunk | void> | BodyChunk): Promise<boolean> {\n const asyncIterator = (async function* () {\n if (body instanceof ReadableStream) {\n const reader = body.getReader();\n let done: boolean;\n do {\n const {value, done: doneReading} = await reader.read();\n done = doneReading;\n if (value !== undefined) {\n yield value;\n }\n } while (!done);\n }\n else {\n const value = await body;\n if (value !== undefined) {\n yield value;\n }\n }\n\n })();\n return this.#writeHandler(stream.ReadableStream.from(asyncIterator) as ReadableStream<BodyChunk>);\n }\n\n async end() {\n return await this.body(Promise.resolve());\n }\n\n}\n\nexport class MockClientHttpResponse extends AbstractHttpResponse<ReadonlyHttpHeaders> implements ClientHttpResponse {\n #statusCode: HttpStatusCode;\n #body: ReadableStream<BodyChunk> = stream.ReadableStream.from([]) as ReadableStream<BodyChunk>;\n constructor(status: number | HttpStatusCode) {\n super(new MapHttpHeaders());\n this.#statusCode = httpStatusCode(status);\n }\n\n get statusCode(): HttpStatusCode {\n return this.#statusCode;\n }\n\n addHeader(name: string, value: string | (readonly string[])): this {\n (this.headers as MutableHttpHeaders).add(name, value);\n return this;\n }\n\n setHeader(name: string, value: ReadonlyHeaderValue): this {\n (this.headers as MutableHttpHeaders).set(name, value);\n return this;\n }\n\n setBody(body: string, charset?: BufferEncoding): this {\n this.#body = stream.ReadableStream.from([Buffer.from(body, charset)]) as ReadableStream<BodyChunk>;\n return this;\n }\n\n set body(body: ReadableStream<BodyChunk>) {\n this.#body = body;\n }\n\n get body() {\n return this.#body;\n }\n\n async blob() {\n const chunks: BodyChunk[] = [];\n if (this.body !== undefined) {\n for await (const chunk of this.body) {\n chunks.push(chunk);\n }\n }\n return new Blob(chunks, {type: this.headers.one('content-type') as string || 'application/octet-stream'});\n }\n}\n", "import type { Principal } from '../../types/auth';\nimport type {\n BodyChunk,\n HeaderValue,\n HeaderValues,\n HttpCookie,\n HttpMethod,\n HttpStatusCode,\n MutableHttpHeaders,\n ReadonlyHeaderValues,\n ReadonlyHttpHeaders,\n ResponseCookie\n} from '../../types/web/http'\n\nimport type {\n RequestPath,\n ServerHttpRequest,\n ServerHttpResponse,\n ServerWebExchange,\n SslInfo\n} from '../../types/web/server';\nimport { AbstractHttpResponse } from '../http/exchange.ts';\nimport { AbstractHttpHeaders } from '../http/headers.ts';\nimport { httpStatusCode } from '../http/status.ts';\nimport type { X509Certificate } from 'node:crypto';\nimport http from 'node:http';\nimport http2 from 'node:http2';\nimport net from 'node:net';\nimport type { TLSSocket } from 'node:tls';\nimport { AbstractServerHttpRequest } from '../http/server/exchange.ts';\nimport type { ServerCodecConfigurer } from '../http/codec/types.ts';\n\nexport class ExtendedHttpIncomingMessage extends http.IncomingMessage {\n // circular reference to the exchange\n exchange?: ServerWebExchange;\n\n upgradeHead?: Buffer<ArrayBufferLike>\n\n\n get urlBang(): string {\n return this.url!;\n }\n\n get socketEncrypted(): boolean {\n // see tls.TLSSocket#encrypted\n return this.socket['encrypted'] === true;\n }\n}\n\nexport class ExtendedHttpServerResponse<Request extends ExtendedHttpIncomingMessage = ExtendedHttpIncomingMessage> extends http.ServerResponse<Request> {\n\n markHeadersSent(): void {\n this['_header'] = true; // prevent response from being sent\n }\n\n getRawHeaderNames(): string[] {\n return super['getRawHeaderNames']();\n }\n}\n\nexport abstract class AbstractServerHttpResponse extends AbstractHttpResponse<MutableHttpHeaders> {\n #cookies: ResponseCookie[] = [];\n #statusCode?: HttpStatusCode;\n #state: 'new' | 'committing' | 'commit-action-failed' | 'committed' = 'new';\n #commitActions: (() => Promise<void>)[] = [];\n\n setStatusCode(statusCode?: HttpStatusCode): boolean {\n if (this.#state === 'committed') {\n return false;\n }\n else {\n this.#statusCode = statusCode;\n return true;\n }\n }\n\n setRawStatusCode(statusCode?: number): boolean {\n return this.setStatusCode(statusCode === undefined ? undefined : httpStatusCode(statusCode));\n };\n\n get statusCode(): HttpStatusCode | undefined {\n return this.#statusCode;\n }\n\n addCookie(cookie: ResponseCookie): this {\n if (this.#state === 'committed') {\n throw new Error(`Cannot add cookie ${JSON.stringify(cookie)} because HTTP response has already been committed`);\n }\n this.#cookies.push(cookie);\n return this;\n }\n\n abstract getNativeResponse<T>(): T;\n\n beforeCommit(action: () => Promise<void>): void {\n this.#commitActions.push(action);\n }\n\n get commited(): boolean {\n const state = this.#state;\n return state !== 'new' && state !== 'commit-action-failed';\n }\n\n async body(body: ReadableStream<BodyChunk> | Promise<BodyChunk | void> | BodyChunk): Promise<boolean> {\n if (body instanceof ReadableStream) {\n throw new Error('ReadableStream body not supported yet');\n }\n const buffer = await body;\n try {\n // touch buffers if needed\n\n return await this.doCommit(async () => {\n\n return await this.bodyInternal(Promise.resolve(buffer));\n\n }).catch(error => {\n // release buffers\n throw error;\n });\n }\n catch (error) {\n // clear content headers\n throw error;\n }\n }\n\n abstract bodyInternal(body: Promise<BodyChunk | void>): Promise<boolean>;\n\n async end(): Promise<boolean> {\n if (!this.commited) {\n return this.doCommit(async () => {\n return await this.bodyInternal(Promise.resolve());\n });\n }\n else {\n return Promise.resolve(false);\n }\n }\n\n protected doCommit(writeAction?: () => Promise<boolean>): Promise<boolean> {\n const state = this.#state;\n let allActions = Promise.resolve();\n if (state === 'new') {\n this.#state = 'committing';\n if (this.#commitActions.length > 0) {\n allActions = this.#commitActions\n .reduce(\n (acc, cur) => acc.then(() => cur()),\n Promise.resolve())\n .catch((_error) => {\n const state = this.#state;\n if (state === 'committing') {\n this.#state = 'commit-action-failed';\n // clear content headers\n }\n });\n }\n }\n else if (state === 'commit-action-failed') {\n this.#state = 'committing';\n // skip commit actions\n } else {\n return Promise.resolve(false);\n }\n\n allActions = allActions.then(() => {\n this.applyStatusCode();\n this.applyHeaders();\n this.applyCookies();\n this.#state = 'committed';\n });\n\n\n return allActions.then(async () => {\n return writeAction !== undefined ? await writeAction() : true;\n });\n }\n\n protected applyStatusCode(): void {}\n protected applyHeaders(): void {}\n protected applyCookies(): void {}\n}\nexport class HttpServerRequest extends AbstractServerHttpRequest implements ServerHttpRequest {\n\n #url?: URL;\n #cookies?: HttpCookie[];\n readonly #req: ExtendedHttpIncomingMessage;\n\n constructor(req: ExtendedHttpIncomingMessage) {\n super(new IncomingMessageHeaders(req));\n this.#req = req;\n }\n\n getNativeRequest<T>(): T {\n return this.#req as T;\n }\n\n get upgrade() {\n return this.#req['upgrade'];\n }\n\n get http2(): boolean {\n return this.#req.httpVersionMajor >= 2;\n }\n\n get path() {\n return this.URL?.pathname;\n }\n\n get URL() {\n this.#url ??= new URL(this.#req.urlBang, `${this.protocol}://${this.host}`);\n return this.#url;\n }\n\n get query() {\n return this.URL?.search;\n }\n\n get method() {\n return this.#req.method as HttpMethod;\n }\n\n get host() {\n let dh: string | undefined = undefined;\n if (this.#req.httpVersionMajor >= 2) {\n dh = (this.#req.headers as http2.IncomingHttpHeaders)[':authority'];\n }\n dh ??= this.#req.socket.remoteAddress;\n return super.parseHost(dh);\n }\n\n get protocol() {\n let dp: string | undefined = undefined;\n if (this.#req.httpVersionMajor > 2) {\n dp = (this.#req.headers as http2.IncomingHttpHeaders)[':scheme'];\n }\n dp ??= this.#req.socketEncrypted ? 'https' : 'http';\n return super.parseProtocol(dp);\n }\n\n get socket() {\n return this.#req.socket;\n }\n\n get remoteAddress(): net.AddressInfo | undefined {\n const family = this.#req.socket.remoteFamily;\n const address = this.#req.socket.remoteAddress;\n const port = this.#req.socket.remotePort;\n const remoteAddress = (!family || !address || !port) ? undefined : { family, address, port };\n return super.parseRemoteAddress(remoteAddress) ?? remoteAddress;\n }\n\n protected initSslInfo(): SslInfo | undefined {\n if (this.#req.socketEncrypted) {\n return new DefaultSslInfo(this.#req.socket as TLSSocket);\n }\n }\n\n get cookies(): HttpCookie[] {\n this.#cookies ??= super.cookies\n return this.#cookies;\n }\n\n get body(): ReadableStream<BodyChunk> {\n return http.IncomingMessage.toWeb(this.#req) as ReadableStream<BodyChunk>;\n }\n\n async blob() {\n const chunks: BodyChunk[] = [];\n if (this.body !== undefined) {\n for await (const chunk of this.body) {\n chunks.push(chunk);\n }\n }\n return new Blob(chunks, {type: this.headers.one('content-type') as string || 'application/octet-stream'});\n }\n\n\n async text() {\n const blob = await this.blob();\n return await blob.text();\n }\n\n async formData() {\n const blob = await this.blob();\n const text = await blob.text();\n return new URLSearchParams(text);\n }\n\n async json() {\n const blob = await this.blob();\n if (blob.size === 0) {\n return undefined;\n }\n const text = await blob.text();\n return JSON.parse(text);\n }\n\n\n protected initId(): string {\n const remoteIp = this.#req.socket.remoteAddress;\n if (!remoteIp) {\n throw new Error('Socket has no remote address');\n }\n return `${remoteIp}:${this.#req.socket.remotePort}`;\n }\n}\n\nclass DefaultSslInfo implements SslInfo {\n readonly peerCertificate?: X509Certificate;\n constructor(socket: TLSSocket) {\n this.peerCertificate = socket.getPeerX509Certificate();\n }\n}\n\nclass IncomingMessageHeaders extends AbstractHttpHeaders<ReadonlyHeaderValues> implements ReadonlyHttpHeaders {\n readonly #msg: ExtendedHttpIncomingMessage;\n\n constructor(msg: ExtendedHttpIncomingMessage) {\n super();\n this.#msg = msg;\n }\n\n has(name: string): boolean {\n return this.#msg.headers[name] !== undefined;\n }\n\n get(name: string): string | (readonly string[]) | undefined {\n return this.#msg.headers[name];\n }\n\n list(name: string): string[] {\n return super.toList(name);\n }\n\n one(name: string): string | undefined {\n const value = this.#msg.headers[name];\n if (Array.isArray(value)) {\n return value[0];\n }\n return value;\n }\n\n keys() {\n return Object.keys(this.#msg.headers).values();\n }\n}\n\nclass OutgoingMessageHeaders extends AbstractHttpHeaders<HeaderValues> implements MutableHttpHeaders {\n readonly #msg: ExtendedHttpServerResponse;\n\n constructor(msg: ExtendedHttpServerResponse) {\n super();\n this.#msg = msg;\n }\n\n has(name: string): boolean {\n return this.#msg.hasHeader(name);\n }\n\n keys() {\n return this.#msg.getHeaderNames().values();\n }\n\n get(name: string): HeaderValues {\n return this.#msg.getHeader(name);\n }\n\n one(name: string): HeaderValue {\n const value = this.#msg.getHeader(name);\n if (Array.isArray(value)) {\n return value[0];\n }\n return value;\n }\n\n set(name: string, value: HeaderValues): this {\n if (!this.#msg.headersSent) {\n if (Array.isArray(value)) {\n value = value.map(v => typeof v === 'number' ? String(v) : v);\n } else if (typeof value === 'number') {\n value = String(value);\n }\n\n if (value) {\n this.#msg.setHeader(name, value);\n }\n else {\n this.#msg.removeHeader(name);\n }\n }\n return this;\n }\n\n add(name: string, value: string | (readonly string[])): this {\n if (!this.#msg.headersSent) {\n this.#msg.appendHeader(name, value);\n }\n return this;\n }\n\n list(name: string): string[] {\n return super.toList(name);\n }\n}\n\nexport class HttpServerResponse extends AbstractServerHttpResponse implements ServerHttpResponse {\n readonly #res: ExtendedHttpServerResponse;\n\n constructor(res: ExtendedHttpServerResponse) {\n super(new OutgoingMessageHeaders(res));\n this.#res = res;\n }\n\n getNativeResponse<T>(): T {\n return this.#res as T;\n }\n\n get statusCode(): HttpStatusCode {\n const status = super.statusCode;\n return status ?? {value: this.#res.statusCode};\n }\n\n applyStatusCode() {\n const status = super.statusCode;\n if (status !== undefined) {\n this.#res.statusCode = status.value;\n }\n }\n\n addCookie(cookie: ResponseCookie): this {\n this.headers.add('Set-Cookie', super.setCookieValue(cookie));\n return this;\n }\n\n async bodyInternal(body: Promise<BodyChunk | void>): Promise<boolean> {\n if (!this.#res.headersSent) {\n if (body instanceof ReadableStream) {\n // http.IncomingMessage.fromWeb(body)\n throw new Error('ReadableStream body not supported in response');\n }\n else {\n const chunk = await body;\n return await new Promise<boolean>((resolve, reject) => {\n try {\n if (chunk === undefined) {\n this.#res.end(() => {\n resolve(true);\n });\n } else {\n if (!this.headers.has('content-length')) {\n // set Content-Length if not already set\n if (typeof chunk === 'string') {\n this.headers.set('Content-Length', Buffer.byteLength(chunk));\n }\n else if (chunk instanceof Blob) {\n this.headers.set('Content-Length', chunk.size);\n }\n else {\n this.headers.set('Content-Length', chunk.byteLength);\n }\n }\n this.#res.end(chunk, () => {\n resolve(true);\n });\n }\n } catch (e) {\n reject(e instanceof Error ? e : new Error(`end failed: ${e}`));\n }\n });\n }\n }\n else {\n return false; // already ended\n }\n }\n}\n\nexport class ServerHttpRequestDecorator implements ServerHttpRequest {\n readonly #delegate: ServerHttpRequest;\n\n constructor(request: ServerHttpRequest) {\n this.#delegate = request;\n }\n\n get delegate(): ServerHttpRequest {\n return this.#delegate;\n }\n\n get id(): string {\n return this.#delegate.id;\n }\n\n get method(): HttpMethod {\n return this.#delegate.method;\n }\n\n get path(): string {\n return this.#delegate.path;\n }\n\n get requestPath(): RequestPath {\n return this.#delegate.requestPath;\n }\n\n get protocol() {\n return this.#delegate.protocol;\n }\n\n get host(): string | undefined {\n return this.#delegate.host;\n }\n\n get URL(): URL {\n return this.#delegate.URL;\n }\n\n get headers(): ReadonlyHttpHeaders {\n return this.#delegate.headers;\n }\n\n get cookies(): HttpCookie[] {\n return this.#delegate.cookies;\n }\n\n get remoteAddress() {\n return this.#delegate.remoteAddress;\n }\n\n get upgrade() {\n return this.#delegate.upgrade;\n }\n\n get sslInfo() {\n return this.#delegate.sslInfo;\n }\n\n get body(): ReadableStream<BodyChunk> | undefined {\n return this.#delegate.body;\n }\n async blob(): Promise<Blob> {\n return await this.#delegate.blob();\n }\n async text(): Promise<string> {\n return await this.#delegate.text();\n }\n async formData(): Promise<URLSearchParams> {\n return await this.#delegate.formData();\n }\n async json(): Promise<unknown> {\n return await this.#delegate.json();\n }\n\n toString(): string {\n return `${ServerHttpRequestDecorator.name} [delegate: ${this.delegate.toString()}]`;\n }\n\n public static getNativeRequest<T>(request: ServerHttpRequest): T {\n if (request instanceof AbstractServerHttpRequest) {\n return request.getNativeRequest<T>();\n }\n else if (request instanceof ServerHttpRequestDecorator) {\n return ServerHttpRequestDecorator.getNativeRequest<T>(request.delegate);\n }\n else {\n throw new Error(`Cannot get native request from ${request.constructor.name}`);\n }\n }\n}\nexport class ServerHttpResponseDecorator implements ServerHttpResponse {\n readonly #delegate: ServerHttpResponse;\n\n constructor(response: ServerHttpResponse) {\n this.#delegate = response;\n }\n\n get delegate(): ServerHttpResponse {\n return this.#delegate;\n }\n\n setStatusCode(statusCode: HttpStatusCode): boolean {\n return this.delegate.setStatusCode(statusCode);\n }\n\n setRawStatusCode(statusCode?: number): boolean {\n return this.delegate.setRawStatusCode(statusCode);\n }\n\n get statusCode(): HttpStatusCode {\n return this.delegate.statusCode;\n }\n\n get cookies(): ResponseCookie[] {\n return this.delegate.cookies;\n }\n\n addCookie(cookie: ResponseCookie): this {\n this.delegate.addCookie(cookie);\n return this;\n }\n\n async end(): Promise<boolean> {\n return await this.delegate.end();\n }\n\n async body(body: ReadableStream<BodyChunk> | Promise<BodyChunk | void> | BodyChunk): Promise<boolean> {\n return await this.#delegate.body(body);\n }\n\n get headers(): MutableHttpHeaders {\n return this.#delegate.headers;\n }\n\n toString(): string {\n return `${ServerHttpResponseDecorator.name} [delegate: ${this.delegate.toString()}]`;\n }\n\n public static getNativeResponse<T>(response: ServerHttpResponse): T {\n if (response instanceof AbstractServerHttpResponse) {\n return response.getNativeResponse<T>();\n }\n else if (response instanceof ServerHttpResponseDecorator) {\n return ServerHttpResponseDecorator.getNativeResponse<T>(response.delegate);\n }\n else {\n throw new Error(`Cannot get native response from ${response.constructor.name}`);\n }\n }\n}\n\nexport class ServerWebExchangeDecorator implements ServerWebExchange {\n readonly #delegate: ServerWebExchange;\n\n protected constructor(exchange: ServerWebExchange) {\n this.#delegate = exchange;\n }\n\n get delegate(): ServerWebExchange {\n return this.#delegate;\n }\n\n get request(): ServerHttpRequest {\n return this.#delegate.request;\n }\n\n get response(): ServerHttpResponse {\n return this.#delegate.response;\n }\n\n attribute<T>(name: string): T | undefined {\n return this.#delegate.attribute(name);\n }\n\n get attributes(): Map<string, unknown> {\n return this.#delegate.attributes;\n }\n\n principal<P extends Principal>(): Promise<P | undefined> {\n return this.#delegate.principal();\n }\n\n get logPrefix(): string {\n return this.#delegate.logPrefix;\n }\n\n toString() {\n return `${ServerWebExchangeDecorator.name} [delegate: ${this.delegate}]`;\n }\n}\n\nexport class DefaultWebExchange<Request extends ServerHttpRequest, Response extends ServerHttpResponse> {\n readonly request: Request;\n readonly response: Response;\n readonly #attributes: Map<string, unknown> = new Map();\n #logId?: unknown;\n #logPrefix: string = '';\n\n constructor(request: Request, response: Response, codecConfigurer: ServerCodecConfigurer) {\n this.#attributes[LOG_ID_ATTRIBUTE] = request.id;\n this.request = request;\n this.response = response;\n }\n\n get method(): HttpMethod {\n return this.request.method;\n }\n\n get path(): string | null | undefined {\n return this.request.path;\n }\n\n get attributes(): Map<string, unknown> {\n return this.#attributes;\n }\n\n attribute<T>(name: string): T | undefined {\n return this.attributes.get(name) as T;\n }\n\n principal<P extends Principal>(): Promise<P | undefined> {\n return Promise.resolve(undefined);\n }\n\n get logPrefix(): string {\n const value = this.attribute(LOG_ID_ATTRIBUTE);\n if (this.#logId !== value) {\n this.#logId = value;\n this.#logPrefix = value !== undefined ? `[${value}] ` : '';\n }\n return this.#logPrefix;\n }\n}\n\nexport const LOG_ID_ATTRIBUTE = 'io.interop.web.server.exchange.log_id';\n\n", "import type { PathContainer, PathContainerElement, PathSegment, Separator } from '../../../types/path';\n\nexport function subPath(container: PathContainer, start: number, end?: number): PathContainer {\n const elements = container.elements;\n end = end ?? elements.length;\n if (start === 0 && end === elements.length) {\n return container;\n }\n if (start === end) {\n return DefaultPathContainer.EMPTY_PATH;\n }\n if (!(start >= 0 && start < elements.length)) throw new Error('start index out of bounds: ' + start);\n if (!(start >= 0 && end <= elements.length)) throw new Error('end index out of bounds: ' + end);\n if (!(start < end)) throw new Error('start index must be less than end index: ' + start + ' >= ' + end);\n const slice = elements.slice(start, end);\n const path = slice.map(e => e.value).join('');\n return new DefaultPathContainer(path, slice);\n}\n\nexport function isSeparator(element: PathContainerElement): element is Separator {\n return element.value.length === 1 && element['valueToMatch'] === undefined && element['parameters'] === undefined;\n}\n\nexport function isPathSegment(element: PathContainerElement): element is PathSegment {\n return !isSeparator(element);\n}\n\nexport type Options = {\n readonly separator: number; // char code 0x2f for '/' and 0x2e for '.'\n readonly decodeAndParseParameters: boolean;\n}\nexport const HTTP_OPTIONS: Options = {\n separator: '/'.charCodeAt(0),\n decodeAndParseParameters: true,\n}\n\nexport const MESSAGING_OPTIONS: Options = {\n separator: '.'.charCodeAt(0),\n decodeAndParseParameters: false,\n}\n\nexport function parsePath(path: string, options?: Options): PathContainer {\n return DefaultPathContainer.createFromUrlPath(path, options ?? HTTP_OPTIONS);\n}\n\ntype DefaultSeparator = Separator & { readonly encoded: string };\n\nclass DefaultPathContainer implements PathContainer {\n static readonly EMPTY_PATH: PathContainer = new DefaultPathContainer('', []);\n static readonly #SEPARATORS: Map<number, DefaultSeparator> = new Map([\n ['/'.charCodeAt(0), { value: '/', encoded: '%2F' }],\n ['.'.charCodeAt(0), { value: '.', encoded: '%2E' }],\n ]);\n\n readonly #path: string;\n readonly #elements: readonly PathContainerElement[];\n\n constructor(path: string, elements: PathContainerElement[]) {\n this.#path = path;\n this.#elements = Object.freeze(elements);\n }\n\n get value(): string {\n return this.#path;\n }\n\n get elements(): readonly PathContainerElement[] {\n return this.#elements;\n }\n\n static createFromUrlPath(path: string, options: Options): PathContainer {\n if (path === '') {\n return DefaultPathContainer.EMPTY_PATH;\n }\n const separator = options.separator;\n const separatorElement = DefaultPathContainer.#SEPARATORS.get(separator);\n if (separatorElement === undefined) {\n throw new Error('Unsupported separator: ' + separator);\n }\n\n const elements: PathContainerElement[] = [];\n let start: number;\n if (path.charCodeAt(0) === separator) {\n start = 1;\n elements.push(separatorElement);\n }\n else {\n start = 0;\n }\n\n while (start < path.length) {\n let end = -1;\n for (let i = start; i < path.length; i++) {\n if (path.charCodeAt(i) === separator) {\n end = i;\n break;\n }\n }\n const segment = (end !== -1) ? path.substring(start, end) : path.substring(start);\n\n if (segment.length > 0) {\n elements.push(options.decodeAndParseParameters ?\n DefaultPathContainer.#decodeAndParsePathSegment(segment) :\n DefaultPathSegment.from(segment, separatorElement)\n );\n }\n if (end === -1) {\n break;\n }\n elements.push(separatorElement);\n start = end + 1;\n }\n return new DefaultPathContainer(path, elements);\n }\n\n static #decodeAndParsePathSegment(segment: string): PathSegment {\n const paramsIndex = segment.indexOf(';');\n if (paramsIndex === -1) {\n const valueToMatch = decodeURIComponent(segment);\n return DefaultPathSegment.from(segment, valueToMatch);\n }\n else {\n const valueToMatch = decodeURIComponent(segment.substring(0, paramsIndex));\n const pathParameterContent = segment.substring(paramsIndex);\n const parameters = DefaultPathContainer.#parsePathParameters(pathParameterContent);\n return DefaultPathSegment.from(segment, valueToMatch, parameters);\n }\n }\n\n static #parsePathParameters(content: string): Map<string, readonly string[]> {\n const parameters: Map<string, string[]> = new Map<string, string[]>();\n let start = 1; // skip initial ';'\n while (start < content.length) {\n let end = -1;\n for (let i = start; i < content.length; i++) {\n if (content.charAt(i) === ';') {\n end = i;\n break;\n }\n }\n const parameter = (end !== -1) ? content.substring(start, end) : content.substring(start);\n DefaultPathContainer.#parsePathParameterValue(parameter, parameters);\n if (end === -1) {\n break;\n }\n start = end + 1;\n }\n if (parameters.size > 0) {\n // freeze all value arrays and the map itself for runtime immutability\n for (const values of parameters.values()) {\n Object.freeze(values);\n }\n }\n return parameters;\n }\n\n static #parsePathParameterValue(input: string, output: Map<string, string[]>): void {\n if (input) {\n const eqIndex = input.indexOf('=');\n if (eqIndex !== -1) {\n const name = decodeURIComponent(input.substring(0, eqIndex));\n if (name.trim()) {\n const value = input.substring(eqIndex + 1);\n for (const v of value.split(',')) {\n const values = output.get(name);\n if (values !== undefined) {\n values.push(decodeURIComponent(v));\n }\n else {\n output.set(name, [decodeURIComponent(v)]);\n }\n }\n }\n }\n else {\n const name = decodeURIComponent(input);\n if (name.trim()) {\n const values = output.get(name);\n if (values !== undefined) {\n values.push('');\n }\n else {\n output.set(name, ['']);\n }\n }\n }\n }\n }\n}\n\nclass DefaultPathSegment implements PathSegment {\n static readonly #EMPTY_PARAMS: ReadonlyMap<string, readonly string[]> = new Map<string, readonly string[]>();\n\n static from(value: string, separatorOrValueToMatch: string | DefaultSeparator, parameters?: Map<string, readonly string[]>): PathSegment {\n if (typeof separatorOrValueToMatch === 'string') {\n const valueToMatch = separatorOrValueToMatch;\n return new DefaultPathSegment(value, valueToMatch, parameters);\n }\n else {\n const separator = separatorOrValueToMatch;\n const valueToMatch = (value.includes(separator.encoded)) ? value.replaceAll(separator.encoded, separator.value) : value;\n return DefaultPathSegment.from(value, valueToMatch, parameters);\n }\n }\n\n readonly #value: string;\n readonly #valueToMatch: string;\n readonly #parameters: ReadonlyMap<string, readonly string[]>;\n\n constructor(value: string, valueToMatch: string, parameters: ReadonlyMap<string, readonly string[]> = DefaultPathSegment.#EMPTY_PARAMS) {\n this.#value = value;\n this.#valueToMatch = valueToMatch;\n this.#parameters = parameters;\n }\n\n get value(): string {\n return this.#value;\n }\n\n get valueToMatch(): string {\n return this.#valueToMatch;\n }\n\n get parameters(): ReadonlyMap<string, readonly string[]> {\n return this.#parameters;\n }\n\n}\n", "import type { ReadonlyHttpHeaders } from '../../../types/web/http';\nimport type { RequestPath, SslInfo } from '../../../types/web/server';\nimport type { PathContainer } from '../../../types/path';\nimport { AbstractHttpRequest } from '../exchange.ts';\nimport { parsePath, subPath } from './path.ts';\n\nexport function parseRequestPath(uri: string | URL, contextPath?: string) {\n if (typeof uri === 'string') {\n return DefaultRequestPath.parse(uri, contextPath);\n }\n else {\n return parseRequestPath(uri.href, contextPath);\n }\n}\n\nclass DefaultRequestPath implements RequestPath {\n\n static #initContextPath(path: PathContainer, contextPath?: string): PathContainer {\n if (!(contextPath && contextPath.trim()) || contextPath.charAt(0) !== '/') {\n return parsePath('');\n }\n\n DefaultRequestPath.#validateContextPath(path.value, contextPath);\n\n const length = contextPath.length;\n let counter = 0;\n\n for (let i = 0; i < path.elements.length; i++) {\n const element = path.elements[i];\n counter += element.value.length;\n if (length === counter) {\n return subPath(path, 0, i + 1);\n }\n }\n\n // should not reach here\n throw new Error(`Failed to initialize context path: '${contextPath}' for request path: '${path.value}'`);\n }\n\n static #validateContextPath(fullPath: string, contextPath: string): void {\n const length = contextPath.length;\n if (contextPath.charAt(0) !== '/' || contextPath.charAt(length - 1) === '/') {\n throw new Error(`Invalid context path: '${contextPath}'. Context path must start with '/' and must not end with '/'`);\n }\n if (!fullPath.startsWith(contextPath)) {\n throw new Error(`Invalid context path: '${contextPath}'. Context path must be a prefix of request path: '${fullPath}'`);\n }\n if (fullPath.length > length && fullPath.charAt(length) !== '/') {\n throw new Error(`Invalid context path: '${contextPath}'. Context path must match to full path segments for request path: '${fullPath}'`);\n }\n }\n\n static #extractPathWithinApplication(fullPath: PathContainer, contextPath: PathContainer): PathContainer {\n const contextPathLength = contextPath.elements.length;\n return subPath(fullPath, contextPathLength);\n }\n\n static parse(rawPath: string, contextPath?: string) {\n const fullPath = parsePath(rawPath);\n const contextPathContainer = DefaultRequestPath.#initContextPath(fullPath, contextPath);\n const pathWithinApplication = DefaultRequestPath.#extractPathWithinApplication(fullPath, contextPathContainer);\n return new DefaultRequestPath(\n parsePath(rawPath),\n contextPathContainer,\n pathWithinApplication\n )\n }\n\n readonly #fullPath: PathContainer;\n readonly #contextPath: PathContainer;\n readonly #pathWithinApplication: PathContainer;\n\n private constructor(fullPath: PathContainer, contextPath: PathContainer, pathWithinApplication: PathContainer) {\n this.#fullPath = fullPath;\n this.#contextPath = contextPath;\n this.#pathWithinApplication = pathWithinApplication;\n }\n\n // path container\n get value() {\n return this.#fullPath.value;\n }\n\n get elements() {\n return this.#fullPath.elements;\n }\n\n // request path\n get contextPath() {\n return this.#contextPath;\n }\n\n get pathWithinApplication() {\n return this.#pathWithinApplication;\n }\n\n modifyContextPath(contextPath: string): RequestPath {\n const contextPathContainer = DefaultRequestPath.#initContextPath(this, contextPath);\n const pathWithinApplication = DefaultRequestPath.#extractPathWithinApplication(this, contextPathContainer);\n return new DefaultRequestPath(\n this,\n contextPathContainer,\n pathWithinApplication\n );\n }\n\n toString(): string {\n return this.#fullPath.toString();\n }\n}\n\nexport abstract class AbstractServerHttpRequest extends AbstractHttpRequest<ReadonlyHttpHeaders> {\n #sslInfo?: SslInfo\n #path?: RequestPath\n #contextPath?: string;\n\n abstract getNativeRequest<T>(): T;\n\n get requestPath(): RequestPath {\n if (this.#path === undefined) {\n this.#path = parseRequestPath(this.URL.pathname, this.#contextPath)\n }\n return this.#path;\n }\n\n protected abstract initSslInfo(): SslInfo | undefined;\n\n get sslInfo(): SslInfo | undefined {\n if (this.#sslInfo === undefined) {\n this.#sslInfo = this.initSslInfo();\n }\n return this.#sslInfo;\n }\n}\n", "import * as GatewayLogging from '@interopio/gateway/logging/core';\n\nexport type Logger = GatewayLogging.Logger;\n\nexport default function getLogger(name: string): Logger {\n return GatewayLogging.getLogger(`gateway.server.${name}`);\n}\n\n// This function is used to ensure that RegExp objects are displayed correctly when logging.\nexport function regexAwareReplacer<T>(_key: string, value: T): string | T {\n return value instanceof RegExp ? value.toString() : value;\n}\n", "export function isLoggingSuppressed(hints?: Map<string, unknown>): boolean {\n return hints?.get('io.gateway.logging.suppress') === true;\n}\n\nexport const LOG_PREFIX_HINT = 'io.gateway.logging.prefix';\n\nexport function getLogPrefix(hints?: Map<string, unknown>): string {\n if (hints?.has(LOG_PREFIX_HINT)) {\n return (hints.get(LOG_PREFIX_HINT) as string) ?? '';\n }\n return '';\n}\n", "import { MIMEType } from 'node:util';\nimport getLogger, { type Logger } from '../logger.ts';\nimport { ALL, createMimeType, isCompatibleWith } from '../utils/mime-type-utils.ts';\nimport { getLogPrefix, isLoggingSuppressed } from './hints.ts';\nimport type { Encoder } from './types.ts';\n\nexport abstract class AbstractEncoder<T> implements Encoder<T> {\n #encodableMimeTypes: readonly MIMEType[];\n protected logger: Logger = getLogger('codec.encoder');\n\n protected constructor(...supportedMimeTypes: MIMEType[]) {\n this.#encodableMimeTypes = [...supportedMimeTypes];\n }\n\n setLogger(logger: Logger) {\n this.logger = logger;\n }\n\n encodableMimeTypes(): readonly MIMEType[] {\n return this.#encodableMimeTypes;\n }\n\n canEncode(type, mimeType?: MIMEType): boolean {\n if (mimeType === undefined) {\n return true;\n }\n for (const supportedMimeType of this.#encodableMimeTypes) {\n if (isCompatibleWith(mimeType, supportedMimeType)) {\n return true;\n }\n }\n return false;\n }\n\n abstract encode(input: Promise<T> | T, mimeType?: MIMEType, hints?: Map<string, unknown>): Promise<BlobPart>;\n}\n\nexport class BlobEncoder extends AbstractEncoder<BlobPart> {\n constructor() {\n super(ALL);\n }\n\n canEncode(type, mimeType?: MIMEType): boolean {\n return super.canEncode(type, mimeType);\n }\n\n async encode(input: Promise<BlobPart> | BlobPart, mimeType?: MIMEType, hints?: Map<string, unknown>): Promise<BlobPart> {\n const part = await input;\n if (this.logger.enabledFor('debug') && !isLoggingSuppressed(hints)) {\n this.#logValue(part);\n }\n return part;\n }\n\n #logValue(part: BlobPart, hints?: Map<string, unknown>): void {\n const prefix = getLogPrefix(hints);\n this.logger.debug(`${prefix}Encoding value of type ${typeof part} with size ${part['byteLength'] ?? part['size'] ?? part['length']}`);\n }\n}\n\n\nexport class StringEncoder extends AbstractEncoder<string> {\n private constructor(...mimeTypes: MIMEType[]) {\n super(...mimeTypes);\n }\n\n canEncode(type, mimeType?: MIMEType): boolean {\n return super.canEncode(type, mimeType) && type === 'string';\n }\n\n async encode(input: Promise<string> | string, mimeType?: MIMEType, hints?: Map<string, unknown>): Promise<BlobPart> {\n input = await input;\n if (!isLoggingSuppressed(hints) && this.logger.enabledFor('debug')) {\n const logPrefix = getLogPrefix(hints);\n const traceEnabled = this.logger.enabledFor('trace');\n this.logger.debug(`${logPrefix}Writing ${traceEnabled ? `${input}` : `${input.substring(0, 100)}...`}`);\n }\n return input;\n }\n\n static textPlainOnly(): StringEncoder {\n return new StringEncoder(createMimeType('text','plain', 'utf-8'));\n }\n static allMimeTypes(): StringEncoder {\n return new StringEncoder(createMimeType('text', 'plain', 'utf-8'), ALL);\n }\n}\n", "import getLogger, { Logger } from '../../logger.ts';\n\nexport abstract class LoggingCodecSupport {\n protected log: Logger = getLogger('http.codec');\n #enableLoggingRequestDetails = false;\n\n set enableLoggingRequestDetails(enable: boolean) {\n this.#enableLoggingRequestDetails = enable;\n }\n\n get enableLoggingRequestDetails(): boolean {\n return this.#enableLoggingRequestDetails;\n }\n}\n", "import { HttpMessageReader } from './types.ts';\nimport { MediaType } from '../media-type.ts';\nimport { isCompatibleWith } from '../../utils/mime-type-utils.ts';\nimport type { HttpInputMessage } from '../../../types/web/http';\nimport { LoggingCodecSupport } from './core.ts';\n\nexport class MultipartHttpMessageReader extends LoggingCodecSupport implements HttpMessageReader<FormData> {\n static readonly MEDIA_TYPES = Object.freeze([MediaType.MULTIPART_FORM_DATA]);\n #partReader: HttpMessageReader<[string, FormDataEntryValue]>;\n\n constructor(partReader: HttpMessageReader<[string, FormDataEntryValue]>) {\n super();\n this.#partReader = partReader;\n }\n\n get partReader() {\n return this.#partReader;\n }\n\n getReadableMediaTypes(): ReadonlyArray<MediaType> {\n return MultipartHttpMessageReader.MEDIA_TYPES;\n }\n\n\n canRead(type, mediaType?: MediaType): boolean {\n return this.#supportsMediaType(mediaType) && (type.name === FormData.name);\n }\n\n #supportsMediaType(mediaType?: MediaType): boolean {\n if (mediaType === undefined) return true;\n\n for (const supportedMediaType of MultipartHttpMessageReader.MEDIA_TYPES) {\n if (isCompatibleWith(supportedMediaType, mediaType)) {\n return true;\n }\n }\n return false;\n }\n\n async readPromise(type, message: HttpInputMessage, hints: Map<string, unknown>): Promise<FormData> {\n const stream = this.#partReader.read(type, message, hints);\n const result = new FormData();\n for await (const [name, value] of stream) {\n result.append(name, value)\n }\n return result;\n }\n\n\n read(type, message: HttpInputMessage, hints: Map<string, unknown>): ReadableStream<FormData> {\n throw new Error(`not implemented yet`);\n }\n\n}\n\n\nexport class DefaultPartHttpMessageReader extends LoggingCodecSupport implements HttpMessageReader<[string, FormDataEntryValue]> {\n getReadableMediaTypes(): ReadonlyArray<MediaType> {\n return [MediaType.MULTIPART_FORM_DATA];\n }\n\n canRead(type, mediaType?: MediaType): boolean {\n return type === 'string' || type.name === File.name && (\n mediaType === undefined || isCompatibleWith(MediaType.MULTIPART_FORM_DATA, mediaType)\n );\n }\n\n readPromise(type, message: HttpInputMessage, hints: Map<string, unknown>): Promise<[string, FormDataEntryValue]> {\n throw new Error(`not implemented yet`);\n }\n\n read(type, message: HttpInputMessage, hints: Map<string, unknown>): ReadableStream<[string, FormDataEntryValue]> {\n throw new Error(`not implemented yet`);\n }\n}\n", "import type {\n CodecConfigurer,\n DefaultCodecs,\n HttpMessageReader,\n HttpMessageWriter,\n ServerCodecConfigurer,\n ServerDefaultCodecs\n} from './types.ts';\nimport type { HttpOutputMessage, MutableHttpHeaders } from '../../../types/web/http';\nimport { AbstractEncoder, BlobEncoder, StringEncoder } from '../../codec/encoder.ts';\nimport type { Encoder } from '../../codec/types.ts';\nimport { MediaType } from '../media-type.ts';\nimport { isConcrete } from '../../utils/mime-type-utils.ts';\nimport { getContentType } from '../headers.ts';\nimport { DefaultPartHttpMessageReader, MultipartHttpMessageReader } from './multipart.ts';\n\n\nclass EncoderHttpMessageWriter<T> implements HttpMessageWriter {\n readonly #encoder: Encoder<T>;\n readonly #mediaTypes: readonly MediaType[];\n #defaultMediaType?: MediaType;\n\n constructor(encoder: Encoder<T>) {\n EncoderHttpMessageWriter.initLogger(encoder);\n this.#encoder = encoder;\n this.#mediaTypes = MediaType.asMediaTypes(...encoder.encodableMimeTypes());\n this.#defaultMediaType = this.#mediaTypes.find(mediaType => isConcrete(mediaType));\n }\n\n get encoder(): Encoder<T> {\n return this.#encoder;\n }\n\n getWriteableMediaTypes(): ReadonlyArray<MediaType> {\n return this.#mediaTypes;\n }\n\n canWrite(type, mediaType?: MediaType): boolean {\n return this.#encoder.canEncode(type, mediaType);\n }\n\n async write(input: Promise<T> | T, type, message: HttpOutputMessage<MutableHttpHeaders>, mediaType?: MediaType, hints?: Map<string, unknown>): Promise<void> {\n const resolvedMediaType = this.#updateContentType(message, mediaType);\n const part = this.#encoder.encode(input, resolvedMediaType, hints);\n await message.body(part);\n }\n\n private static initLogger(encoder: Encoder<unknown>): void {\n if (encoder instanceof AbstractEncoder) {\n // encoder.setLogger();\n }\n }\n\n #updateContentType(message: HttpOutputMessage<MutableHttpHeaders>, mediaType?: MediaType) {\n let resolvedMediaType = getContentType(message.headers);\n if (resolvedMediaType) {\n return resolvedMediaType;\n }\n let fallback = this.#defaultMediaType;\n resolvedMediaType = (useFallback(mediaType, fallback) ? fallback : mediaType);\n if (resolvedMediaType) {\n resolvedMediaType = addDefaultCharsetIfNeeded(resolvedMediaType, fallback);\n message.headers.set('Content-Type', resolvedMediaType.toString());\n }\n }\n}\n\nfunction addDefaultCharsetIfNeeded(main: MediaType, defaultType?: MediaType): MediaType {\n if (!main.params.has('charset') && defaultType !== undefined) {\n const defaultCharset = defaultType.params.get('charset');\n if (defaultCharset) {\n const result = MediaType.parseMediaType(main.toString());\n result.params.set('charset', defaultCharset);\n return result;\n }\n }\n return main;\n}\n\nfunction useFallback(main?: MediaType, fallback?: MediaType): boolean {\n return (main === undefined || !isConcrete(main) || main.essence === MediaType.APPLICATION_OCTET_STREAM.essence) && fallback !== undefined;\n}\n\nclass BaseDefaultCodecs implements DefaultCodecs {\n #multipartReader?: HttpMessageReader<unknown>;\n #maxInMemorySize?: number;\n #enableLoggingRequestDetails?: boolean;\n #registerDefaults = true;\n #writers = Array<HttpMessageWriter>();\n #readers = Array<HttpMessageReader>();\n\n constructor() {\n this.initReaders();\n this.initWriters();\n }\n\n multipartReader(reader: HttpMessageReader<unknown>) {\n this.#multipartReader = reader;\n this.initReaders();\n }\n\n registerDefaults(registerDefaults: boolean) {\n if (this.#registerDefaults !== registerDefaults) {\n this.#registerDefaults = registerDefaults;\n this.initReaders();\n this.initWriters();\n }\n }\n\n protected initReaders(): void {\n this.#readers.length = 0;\n if (!this.#registerDefaults) {\n return;\n }\n\n if (this.#multipartReader !== undefined) {\n this.addCodec(this.#readers, this.#multipartReader);\n }\n else {\n const partReader = new DefaultPartHttpMessageReader();\n this.addCodec(this.#readers, partReader);\n this.addCodec(this.#readers, new MultipartHttpMessageReader(partReader));\n }\n }\n\n protected initWriters(): void {\n this.#writers.length = 0;\n if (!this.#registerDefaults) {\n return;\n }\n this.#writers.push(...this.#getBaseWriters());\n this.extendWriters(this.#writers);\n }\n\n protected extendWriters(writers: Array<HttpMessageWriter>): void {\n }\n\n #getBaseWriters(): HttpMessageWriter[] {\n if (!this.#registerDefaults) {\n return [];\n }\n const writers = Array<HttpMessageWriter>();\n this.addCodec(writers, new EncoderHttpMessageWriter(new BlobEncoder()));\n return writers;\n }\n\n maxInMemorySize(bytes: number) {\n if (this.#maxInMemorySize !== bytes) {\n this.#maxInMemorySize = bytes;\n this.initReaders();\n }\n }\n\n enableLoggingRequestDetails(enable: boolean) {\n if (this.#enableLoggingRequestDetails !== enable) {\n this.#enableLoggingRequestDetails = enable;\n this.initReaders();\n this.initWriters();\n }\n }\n\n get catchAllReaders() {\n if (!this.#registerDefaults) {\n return [];\n }\n const readers = Array<HttpMessageReader>();\n\n return readers;\n }\n\n get typedWriters() {\n return this.#writers;\n }\n\n get typedReaders() {\n return this.#readers;\n }\n\n get catchAllWriters(): readonly HttpMessageWriter[]{\n if (!this.#registerDefaults) {\n return [];\n }\n const result = Array<HttpMessageWriter>();\n this.addCodec(result, new EncoderHttpMessageWriter(StringEncoder.allMimeTypes()));\n return result;\n }\n\n protected addCodec<T >(codecs: Array<T>, codec: T) {\n this.#initCodec(codec);\n codecs.push(codec);\n }\n\n #initCodec(codec: unknown): void {\n if (codec instanceof EncoderHttpMessageWriter) {\n codec = codec.encoder;\n }\n if (codec === undefined) {\n return;\n }\n const size = this.#maxInMemorySize;\n if (size !== undefined) {\n // todo\n }\n\n const enable = this.#enableLoggingRequestDetails;\n if (enable !== undefined) {\n if (codec instanceof MultipartHttpMessageReader) {\n codec.enableLoggingRequestDetails = enable;\n }\n if (codec instanceof DefaultPartHttpMessageReader) {\n codec.enableLoggingRequestDetails = enable;\n }\n }\n }\n}\nabstract class BaseCodecConfigurer implements CodecConfigurer {\n protected readonly baseDefaultCodecs: BaseDefaultCodecs;\n\n protected constructor(defaultCodecs: BaseDefaultCodecs) {\n this.baseDefaultCodecs = defaultCodecs;\n }\n\n get defaultCodecs(): DefaultCodecs {\n return this.baseDefaultCodecs;\n }\n\n registerDefaults(registerDefaults: boolean) {\n this.baseDefaultCodecs.registerDefaults(registerDefaults);\n }\n\n get readers() {\n const result = new Array<HttpMessageReader>();\n result.push(...this.baseDefaultCodecs.typedReaders);\n result.push(...this.baseDefaultCodecs.catchAllReaders);\n return result;\n }\n\n get writers(): readonly HttpMessageWriter[] {\n const result = new Array<HttpMessageWriter>();\n result.push(...this.baseDefaultCodecs.typedWriters);\n result.push(...this.baseDefaultCodecs.catchAllWriters);\n return result;\n }\n\n}\n\nclass ServerDefaultCodecsImpl extends BaseDefaultCodecs implements ServerDefaultCodecs {\n\n}\nclass DefaultServerCodecConfigurer extends BaseCodecConfigurer implements ServerCodecConfigurer {\n constructor() {\n super(new ServerDefaultCodecsImpl());\n }\n}\n\nfunction createServerCodecConfigurer(): ServerCodecConfigurer {\n return new DefaultServerCodecConfigurer();\n}\n\nexport default {\n serverConfigurer: {\n create: createServerCodecConfigurer\n }\n}\n", "import type { Principal } from '../../../types/auth';\nimport type {\n BodyChunk,\n HttpMethod, HttpResponse,\n MutableHttpHeaders,\n ReadonlyHeaderValue\n} from '../../../types/web/http';\nimport { ServerHttpRequest, SslInfo } from '../../../types/web/server';\nimport { AbstractServerHttpResponse, DefaultWebExchange } from '../../server/exchange.ts';\nimport { MapHttpHeaders } from '../../http/headers.ts';\nimport codecConfig from '../../http/codec/config.ts';\nimport stream from 'node:stream/web';\nimport { AbstractServerHttpRequest } from '../../http/server/exchange.ts';\n\nexport class MockServerHttpRequest extends AbstractServerHttpRequest implements ServerHttpRequest {\n readonly #url: URL;\n readonly #sslInfo?: SslInfo;\n #body?: Blob;\n upgrade = false;\n\n constructor(url: URL | string, method?: HttpMethod) {\n super(new MapHttpHeaders());\n if (typeof url === 'string') {\n if (URL.canParse(url)) {\n url = new URL(url);\n }\n else if (URL.canParse(url, 'http://localhost')) {\n url = new URL(url, 'http://localhost');\n }\n else {\n throw new TypeError('URL cannot parse url');\n }\n }\n this.#url = url;\n this.method = method ?? 'GET';\n this.setHeader('Host', this.#url.hostname);\n this.path = this.#url.pathname ?? '/';\n }\n\n static get(url: URL | string) {\n return new MockServerHttpRequest(url, 'GET');\n }\n\n static post(url: URL | string) {\n return new MockServerHttpRequest(url, 'POST');\n }\n\n static options(url: URL | string) {\n return new MockServerHttpRequest(url, 'OPTIONS');\n }\n\n protected initSslInfo(): SslInfo | undefined {\n return this.#sslInfo;\n }\n\n getNativeRequest<T>(): T {\n throw new Error(`This is a mock. No running server, no native request available.`);\n }\n\n method: HttpMethod;\n path: string;\n\n get host() {\n return super.parseHost(this.#url.host);\n }\n\n get protocol() {\n return super.parseProtocol((this.#url.protocol).slice(0, -1));\n }\n\n get body() {\n if (this.#body !== undefined) {\n const blob = this.#body;\n const asyncIterator: AsyncGenerator<BodyChunk> = (async function* () {\n const bytes = await blob.bytes();\n yield bytes;\n })();\n return stream.ReadableStream.from(asyncIterator) as ReadableStream<BodyChunk>;\n }\n }\n\n blob(): Promise<Blob> {\n const body = this.#body;\n return body ? Promise.resolve(body) : Promise.reject(new Error(`no body set`));\n }\n\n async text() {\n const blob = await this.blob();\n return await blob.text();\n }\n\n async formData() {\n const blob = await this.blob();\n const text = await blob.text();\n return new URLSearchParams(text);\n }\n\n async json() {\n const blob = await this.blob();\n if (blob.size === 0) {\n return undefined;\n }\n const text = await blob.text();\n return JSON.parse(text);\n }\n\n async writeBody(body?: ReadableStream<BodyChunk> | Promise<BodyChunk> | BodyChunk) {\n if (body === undefined) {\n this.#body = new Blob([]);\n return;\n }\n if (body instanceof ReadableStream) {\n const chunks: BodyChunk[] = [];\n const reader = body.getReader();\n let done = false;\n while (!done) {\n const { value, done: readDone } = await reader.read();\n if (readDone) {\n done = true;\n }\n else {\n chunks.push(value);\n }\n }\n this.#body = new Blob(chunks);\n }\n else {\n body = await body;\n if (typeof body === 'string') {\n this.#body = new Blob([body], { type: 'text/plain' });\n }\n else {\n this.#body = new Blob([body]);\n }\n }\n if (!this.headers.has('content-type')) {\n this.setHeader('Content-Type', this.#body.type || 'application/octet-stream');\n }\n\n }\n\n get URL() {\n return new URL(this.path + this.#url.search + this.#url.hash, `${this.protocol}://${this.host}`);\n }\n\n addHeader(name: string, value: string | (readonly string[])): this {\n (this.headers as MutableHttpHeaders).add(name, value);\n return this;\n }\n\n setHeader(name: string, value: ReadonlyHeaderValue): this {\n (this.headers as MutableHttpHeaders).set(name, value);\n return this;\n }\n}\n\nexport class MockServerHttpResponse extends AbstractServerHttpResponse implements HttpResponse<MutableHttpHeaders> {\n #writeHandler: (body: ReadableStream<BodyChunk>) => Promise<boolean>;\n #body: () => ReadableStream<BodyChunk> = () => {\n throw new Error('No content was written to the response body nor end was called on this response.');\n };\n\n constructor() {\n super(new MapHttpHeaders());\n this.#writeHandler = async (body) => {\n const chunks: BodyChunk[] = [];\n let bodyStream: ReadableStream<BodyChunk> | undefined;\n this.#body = () => {\n bodyStream ??= stream.ReadableStream.from(chunks) as ReadableStream<BodyChunk>;\n return bodyStream;\n };\n\n const reader = body.getReader();\n let done = false;\n do {\n const { value, done: readDone } = await reader.read();\n if (readDone) {\n done = true;\n }\n else {\n chunks.push(value);\n }\n }\n while (!done);\n return true;\n }\n }\n\n get statusCode() {\n return super.statusCode!; // :(\n }\n\n set writeHandler(handler: (body: ReadableStream<BodyChunk>) => Promise<boolean>) {\n this.#body = () => {\n throw new Error('Not available with custom write handler');\n }\n this.#writeHandler = handler;\n }\n\n\n getNativeResponse<T>(): T {\n throw new Error('This is a mock. No running server, no native response.');\n }\n\n protected applyStatusCode(): void {\n }\n\n protected applyHeaders(): void {\n }\n\n protected applyCookies(): void {\n for (const cookie of this.cookies) {\n this.headers.add('Set-Cookie', super.setCookieValue(cookie));\n }\n }\n\n bodyInternal(body: Promise<BodyChunk | void>): Promise<boolean> {\n const it = (async function* () {\n const resolved = await body;\n if (resolved === undefined) {\n return;\n }\n yield resolved;\n })();\n return this.#writeHandler(stream.ReadableStream.from(it) as ReadableStream<BodyChunk>);\n }\n\n async end(): Promise<boolean> {\n return this.doCommit(async () => {\n return await this.#writeHandler(stream.ReadableStream.from([]) as ReadableStream);\n });\n }\n\n getBody() {\n return this.#body();\n }\n}\n\n\nexport class MockWebExchange extends DefaultWebExchange<MockServerHttpRequest, MockServerHttpResponse> {\n readonly #principal?: Principal;\n\n constructor(request: MockServerHttpRequest, response?: MockServerHttpResponse, principal?: Principal) {\n super(request, response ?? new MockServerHttpResponse(), codecConfig.serverConfigurer.create());\n this.#principal = principal;\n }\n\n static from (request: MockServerHttpRequest): MockWebExchange {\n return new MockWebExchange(request);\n }\n\n principal<P extends Principal>(): Promise<P | undefined> {\n return Promise.resolve(this.#principal as P);\n }\n}\n", "import { ServerHttpResponseDecorator } from './exchange.ts';\n\nexport class HttpHeadResponseDecorator extends ServerHttpResponseDecorator {\n\n}\n\n\n", "import type { ClientHttpConnector } from '../../client/types.js';\nimport { MockClientHttpRequest, MockClientHttpResponse } from '../../mock/client/exchange.ts';\nimport { MockServerHttpRequest, MockServerHttpResponse } from '../../mock/server/exchange.ts';\nimport { BodyChunk, HttpMethod } from '../../../types/web/http';\nimport type { ClientHttpRequest, ClientHttpResponse } from '../../../types/web/client';\n\nimport getLogger from '../../logger.js';\nimport type { ServerHttpRequest, ServerHttpResponse, SslInfo } from '../../../types/web/server';\nimport { HttpHeadResponseDecorator } from '../../server/handler.ts';\nimport stream from 'node:stream/web';\nimport type { HttpHandler } from '../../http/server/types.ts';\n\n\nclass FailureAfterResponseCompletedError extends Error {\n readonly completedResponse: ClientHttpResponse;\n\n constructor(response: ClientHttpResponse, options: { cause?: Error } = {}) {\n super(`error occurred after response was completed: ${response}`, options);\n this.completedResponse = response;\n }\n}\n\ntype Sink<T> = {\n resolve: (value: T | PromiseLike<T>) => void,\n reject: (reason?: unknown) => void,\n promise: Promise<T>\n}\n\nasync function sink<T>(): Promise<Sink<T>> {\n try {\n return await new Promise<Sink<T>>((result, _error) => {\n\n const promise = new Promise<T>((resolve, reject) => {\n Promise.resolve().then(() => {\n result({promise, resolve, reject});\n });\n });\n });\n }\n catch (error) {\n throw error;\n }\n}\n\nexport class HttpHandlerConnector implements ClientHttpConnector {\n static readonly #logger = getLogger('test.http.handler.connector');\n readonly #httpHandler: HttpHandler;\n readonly #sslInfo?: SslInfo;\n\n constructor(httpHandler: HttpHandler, sslInfo?: SslInfo) {\n this.#httpHandler = httpHandler;\n this.#sslInfo = sslInfo;\n }\n\n async connect(method: HttpMethod, uri: URL,\n requestCallback: (request: ClientHttpRequest) => Promise<void>): Promise<ClientHttpResponse> {\n\n const requestWriteSink = await sink<void>();\n const handlerSink = await sink<void>();\n const savedResponse: [ClientHttpResponse | undefined] = [undefined];\n\n const mockClientRequest = new MockClientHttpRequest(uri, method);\n const mockServerResponse = new MockServerHttpResponse();\n\n mockClientRequest.writeHandler = async (responseBody) => {\n this.log('Invoking HttpHandler for ', method, uri);\n const mockServerRequest = await this.adoptRequest(mockClientRequest, responseBody);\n const responseToUse = this.prepareResponse(mockServerResponse, mockServerRequest);\n\n try {\n await this.#httpHandler(mockServerRequest, responseToUse);\n handlerSink.resolve();\n } catch (e) {\n handlerSink.reject(e);\n }\n return true;\n\n }\n\n mockServerResponse.writeHandler = async (responseBody) => {\n this.log('Creating client response for ', method, uri);\n savedResponse[0] = this.adoptResponse(mockServerResponse, responseBody);\n return true;\n }\n this.log('Writing client request for ', method, uri);\n\n requestCallback(mockClientRequest)\n .then(() => {\n requestWriteSink.resolve();\n })\n .catch(error => {\n requestWriteSink.reject(error);\n });\n\n return Promise.all([requestWriteSink.promise, handlerSink.promise])\n .catch((error) => {\n const response = savedResponse[0];\n throw response !== undefined ? new FailureAfterResponseCompletedError(response, {cause: error}) : error;\n }).then(() => {\n const response = savedResponse[0];\n return response ?? this.adoptResponse(mockServerResponse, stream.ReadableStream.from([]) as ReadableStream<BodyChunk>);\n });\n\n }\n\n private log(message: string, method: HttpMethod, uri: URL): void {\n if (HttpHandlerConnector.#logger.enabledFor('debug')) {\n HttpHandlerConnector.#logger.debug(`${message} ${method} \"${uri.href}\"`);\n }\n }\n\n private async adoptRequest(request: MockClientHttpRequest, body: ReadableStream<BodyChunk>): Promise<ServerHttpRequest> {\n const method = request.method;\n const uri = request.URL;\n const headers = request.headers;\n const _cookies = request.cookies;\n const result = new MockServerHttpRequest(uri, method)\n for (const name of headers.keys()) {\n let value = headers.get(name);\n if (value !== undefined) {\n if (typeof value === 'number') {\n value = String(value);\n }\n if (typeof value === 'string') {\n result.setHeader(name, value);\n } else {\n for (const v of value) {\n result.addHeader(name, v);\n }\n }\n }\n }\n await result.writeBody(body)\n return result;\n }\n\n private prepareResponse(response: ServerHttpResponse, request: ServerHttpRequest): ServerHttpResponse {\n return request.method === 'HEAD' ? new HttpHeadResponseDecorator(response) : response;\n\n }\n\n private adoptResponse(response: MockServerHttpResponse, body: ReadableStream<BodyChunk>): ClientHttpResponse {\n const status = response.statusCode;\n const headers = response.headers;\n const _cookies = response.cookies;\n const result = new MockClientHttpResponse(status);\n for (const name of headers.keys()) {\n let value = headers.get(name);\n if (value !== undefined) {\n if (typeof value === 'number') {\n value = String(value);\n }\n if (typeof value === 'string') {\n result.setHeader(name, value);\n } else {\n for (const v of value) {\n result.addHeader(name, v);\n }\n }\n }\n }\n result.body = body;\n return result;\n }\n}\n\n", "import { IOGateway } from '@interopio/gateway';\nimport type { OriginFilters } from '../../types/web/server';\nimport getLogger from '../logger.ts';\n\nconst log = getLogger('gateway.ws.client-verify');\n\nexport type ProcessedOriginFilters\n = Required<Omit<OriginFilters, 'blacklist' | 'whitelist'>>\n //| Required<Omit<GatewayServer.OriginFilters, 'block' | 'allow'>>\n ;\n\nfunction acceptsMissing(originFilters: ProcessedOriginFilters): boolean {\n switch (originFilters.missing) {\n case 'allow': // fall-through\n case 'whitelist':\n return true;\n case 'block': // fall-through\n case 'blacklist':\n return false;\n default:\n return false;\n }\n}\n\nfunction tryMatch(originFilters: ProcessedOriginFilters, origin: string): boolean | undefined {\n const block = originFilters.block ?? originFilters['blacklist'];\n const allow = originFilters.allow ?? originFilters['whitelist'];\n if (block.length > 0 && IOGateway.Filtering.valuesMatch(block, origin)) {\n log.warn(`origin ${origin} matches block filter`);\n return false;\n } else if (allow.length > 0 && IOGateway.Filtering.valuesMatch(allow, origin)) {\n if (log.enabledFor('debug')) {\n log.debug(`origin ${origin} matches allow filter`);\n }\n return true;\n }\n}\n\nfunction acceptsNonMatched(originFilters: ProcessedOriginFilters): boolean {\n switch (originFilters.non_matched) {\n case 'allow': // fall-through\n case 'whitelist':\n return true;\n case 'block': // fall-through\n case 'blacklist':\n return false;\n default:\n return false;\n }\n}\n\nexport function acceptsOrigin(origin?: string, originFilters?: ProcessedOriginFilters): boolean {\n if (!originFilters) {\n return true;\n }\n if (!origin) {\n return acceptsMissing(originFilters);\n } else {\n const matchResult: boolean | undefined = tryMatch(originFilters, origin);\n if (matchResult) {\n return matchResult;\n } else {\n return acceptsNonMatched(originFilters);\n }\n }\n}\n\nexport function regexifyOriginFilters(originFilters?: OriginFilters): ProcessedOriginFilters | undefined {\n if (originFilters) {\n const block = (originFilters.block ?? originFilters.blacklist ?? []).map(IOGateway.Filtering.regexify);\n const allow = (originFilters.allow ?? originFilters.whitelist ?? []).map(IOGateway.Filtering.regexify);\n return {\n non_matched: originFilters.non_matched ?? 'allow',\n missing: originFilters.missing ?? 'allow',\n allow,\n block,\n }\n }\n}\n", "import type {ServerWebExchange} from '../../../types/web/server';\n\nexport type MatchResult = Readonly<{ match: boolean, variables: Readonly<Record<string, string>> }>;\n\nexport interface ServerWebExchangeMatcher {\n /**\n * Matches the given exchange against the matcher.\n * @param exchange The web exchange to match.\n * @returns A promise that resolves to true if the exchange matches, false otherwise.\n */\n (exchange: ServerWebExchange): Promise<MatchResult>;\n\n /**\n * Returns a string representation of the matcher.\n * @returns A string representation of the matcher.\n */\n toString(): string;\n}\n\nexport type ServerWebExchangeMatcherEntry<T> = Readonly<[ServerWebExchangeMatcher, T]>\n\nexport const or: (matchers: ServerWebExchangeMatcher[]) => ServerWebExchangeMatcher = (matchers: ServerWebExchangeMatcher[]): ServerWebExchangeMatcher => {\n return async (exchange: ServerWebExchange): Promise<MatchResult> => {\n for (const matcher of matchers) {\n const result = await matcher(exchange);\n if (result.match) {\n return match();\n }\n }\n return NO_MATCH;\n };\n}\n\nexport const and: (matchers: ServerWebExchangeMatcher[]) => ServerWebExchangeMatcher = (matchers: ServerWebExchangeMatcher[]) => {\n const matcher = async (exchange: ServerWebExchange): Promise<MatchResult> => {\n for (const matcher of matchers) {\n const result = await matcher(exchange);\n if (!result.match) {\n return NO_MATCH;\n }\n }\n return match();\n };\n matcher.toString = () => `and(${matchers.map(m => m.toString()).join(', ')})`;\n return matcher;\n}\n\n\nexport const not: (matcher: ServerWebExchangeMatcher) => ServerWebExchangeMatcher = (matcher: ServerWebExchangeMatcher): ServerWebExchangeMatcher => {\n return async (exchange: ServerWebExchange): Promise<MatchResult> => {\n const result = await matcher(exchange);\n return result.match ? NO_MATCH : match();\n };\n}\n\nexport const anyExchange: ServerWebExchangeMatcher = async (_exchange: ServerWebExchange): Promise<MatchResult> => {\n return match();\n}\nanyExchange.toString = () => 'any-exchange';\n\nconst EMPTY_OBJECT = Object.freeze({});\nexport const NO_MATCH: MatchResult = Object.freeze({match: false, variables: EMPTY_OBJECT});\nexport const match = (variables: Record<string, string> = EMPTY_OBJECT): MatchResult => {\n return { match: true, variables };\n}\n\nexport const pattern: ((pattern: string | RegExp, opts?: {method?: string}) => ServerWebExchangeMatcher) = (pattern, opts) => {\n const method = opts?.method;\n const matcher = async (exchange: ServerWebExchange): Promise<MatchResult> => {\n const request = exchange.request;\n const path = request.path;\n if (method !== undefined && request.method !== method) {\n return NO_MATCH;\n }\n if (typeof pattern === 'string') {\n if (path === pattern) {\n return match();\n }\n return NO_MATCH;\n }\n else {\n const match = pattern.exec(path);\n if (match === null) {\n return NO_MATCH;\n }\n return {match: true, variables: {...match.groups}};\n }\n };\n matcher.toString = () => {\n return `pattern(${pattern.toString()}, method=${method ?? '<any>'})`;\n }\n return matcher\n\n}\nexport const mediaType : ((opts: { mediaTypes: string[], ignoredMediaTypes?: string[], useEquality?: boolean }) => ServerWebExchangeMatcher) = (opts): ServerWebExchangeMatcher => {\n\n const shouldIgnore = (requestedMediaType: string): boolean => {\n if (opts.ignoredMediaTypes !== undefined) {\n for (const ignoredMediaType of opts.ignoredMediaTypes) {\n if (requestedMediaType === ignoredMediaType || ignoredMediaType === '*/*') {\n return true;\n }\n }\n }\n return false;\n }\n\n return async (exchange: ServerWebExchange): Promise<MatchResult> => {\n const request = exchange.request;\n let requestMediaTypes: string[];\n try {\n requestMediaTypes = request.headers.list('accept');\n }\n catch (e) {\n return NO_MATCH;\n }\n for (const requestedMediaType of requestMediaTypes) {\n if (shouldIgnore(requestedMediaType)) {\n continue;\n }\n for (const mediaType of opts.mediaTypes) {\n if (requestedMediaType.startsWith(mediaType)) {\n return match();\n }\n }\n }\n\n return NO_MATCH;\n };\n}\n\nexport const upgradeMatcher: ServerWebExchangeMatcher = async ({request}: ServerWebExchange): Promise<MatchResult> => {\n const upgrade = request.upgrade && request.headers.one('upgrade')?.toLowerCase() === 'websocket';\n return upgrade ? match() : NO_MATCH;\n};\nupgradeMatcher.toString = () => 'websocket upgrade';\n", "import { regexifyOriginFilters } from '../server/ws-client-verify.ts';\nimport type { SecurityContext } from '../server/security/security-context.ts';\nimport { pattern, type ServerWebExchangeMatcher } from '../server/util/matchers.ts';\nimport type { Middleware } from '../server/types.ts';\nimport type { AsyncLocalStorage } from 'node:async_hooks';\nimport type { SocketRoute } from '../server/socket.ts';\nimport type { ServerConfig, ServerCustomizer } from '../../types/config';\nimport type {\n ServerConfigurer,\n ServerConfigurerHandlerSpec,\n ServerConfigurerSocketSpec,\n ServerExchangeOptions,\n ServerWebExchange\n} from '../../types/web/server';\nimport type { AuthorizationRule } from '../../types/auth';\nimport { IOGateway } from '@interopio/gateway';\nimport type { CorsConfig } from '../web/cors/types.ts';\n\nexport type PathPattern = string | RegExp;\nexport type RouteConfig = Readonly<{\n readonly storage: AsyncLocalStorage<{\n exchange: ServerWebExchange,\n securityContext?: Promise<SecurityContext>\n }>,\n readonly serverHeader?: string | false\n readonly corsConfig?: ServerConfig['cors'],\n readonly authConfig?: ServerConfig['auth'],\n readonly middleware: Middleware,\n readonly cors: Array<[PathPattern, CorsConfig | undefined]>,\n readonly authorize: Array<[ServerWebExchangeMatcher, AuthorizationRule]>\n readonly sockets: Map<string, SocketRoute>\n readonly resourcesConfig?: ServerConfig['resources']\n}>\n\nexport async function configure(app: ServerCustomizer, config: ServerConfig, routes: RouteConfig): Promise<void> {\n const applyCors = (request: ServerConfigurerHandlerSpec['request'], options?: ServerExchangeOptions) => {\n // // disable CORS for this route\n // if (options?.cors === false) {\n // const path = request.path as (PathPattern);\n // routes.cors.push([request.path, undefined]);\n // }\n if (options?.cors) {\n const cors: CorsConfig = options.cors === true ? {\n allowOrigins: options.origins?.allow?.map(IOGateway.Filtering.regexify),\n allowMethods: request.method === undefined ? ['*'] : [request.method],\n allowCredentials: options.authorize?.access !== 'permitted' ? true : undefined,\n } : options.cors;\n const path = request.path as (PathPattern);\n routes.cors.push([path, cors]);\n }\n }\n\n const configurer = new class implements ServerConfigurer {\n\n handle(...handlers: Array<ServerConfigurerHandlerSpec>) {\n handlers.forEach(({request, options, handler}) => {\n const matcher = pattern(IOGateway.Filtering.regexify(request.path) as string | RegExp, {method: request.method});\n if (options?.authorize) {\n routes.authorize.push([matcher, options.authorize]);\n }\n\n applyCors(request, options);\n const middleware = async (exchange: ServerWebExchange, next: () => Promise<void>): Promise<void> => {\n const {match, variables} = await matcher(exchange);\n if (match) {\n await handler(exchange, variables);\n } else {\n await next();\n }\n };\n routes.middleware.push(middleware);\n });\n }\n\n socket(...sockets: Array<ServerConfigurerSocketSpec>) {\n for (const {path, factory, options} of sockets) {\n const route = path ?? '/';\n\n // cors and authorize are currently handled for ws\n routes.sockets.set(route, {\n default: path === undefined || path === '/',\n ping: options?.ping,\n factory: factory,\n maxConnections: options?.maxConnections,\n authorize: options?.authorize,\n originFilters: regexifyOriginFilters(options?.origins)\n });\n }\n }\n };\n await app(configurer, config);\n}\n", "type MiddlewareFunction<T> = ((ctx: T, next: (ctx?: T) => Promise<void>) => Promise<void>) | ((ctx: T) => Promise<void>);\n\n// https://github.com/koajs/compose/blob/master/index.js\n/**\n * @typeParam T - Type of context passed through the middleware\n * @param middleware middleware stack\n * @return {MiddlewareFunction}\n */\nexport function compose<T>(...middleware: MiddlewareFunction<T>[]): (ctx: T) => Promise<void> {\n if (!Array.isArray(middleware)) {\n throw new Error('middleware must be array!');\n }\n const fns = middleware.flat();\n for (const fn of fns) {\n if (typeof fn !== 'function') {\n throw new Error('middleware must be compose of functions!');\n }\n }\n return async function (ctx: T, next?: (ctx?: T) => Promise<void>) {\n const dispatch = async (i: number, dispatchedCtx: T): Promise<void> => {\n const fn = i === fns.length ? next : fns[i];\n if (fn === undefined) {\n return;\n }\n let nextCalled = false;\n let nextResolved = false;\n const nextFn = async (nextCtx?: T) => {\n if (nextCalled) {\n throw new Error('next() called multiple times');\n }\n nextCalled = true;\n try {\n return await dispatch(i + 1, nextCtx ?? dispatchedCtx);\n }\n finally {\n nextResolved = true;\n }\n };\n const result = await fn(dispatchedCtx, nextFn);\n if (nextCalled && !nextResolved) {\n throw new Error('middleware resolved before downstream.\\n\\t You are probably missing an await or return statement in your middleware function.');\n }\n return result;\n }\n\n return dispatch(0, ctx);\n }\n}\n", "import type { ClientHttpConnector } from '../../client/types.ts';\nimport { FetchClientHttpConnector } from '../../client/fetch.ts';\nimport type {\n HttpMethod\n} from '../../../types/web/http';\nimport type {\n TestClient,\n TestClientBuilder,\n MockServerSpec\n} from '../../../types/web/test';\nimport type { ServerCustomizer } from '../../../types/config';\nimport { HttpHandlerConnector } from './handler.ts';\nimport { configure, type RouteConfig } from '../../app/route.ts';\nimport { compose } from '../../common/compose.ts';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Middleware, ServerWebExchange, SslInfo } from '../../../types/web/server';\nimport type { SocketRoute } from '../../server/socket.ts';\nimport { WebHttpHandlerBuilder } from '../../web/server/adapter.ts';\n\nexport function bindToApp(app: ServerCustomizer): MockServerSpec {\n return new AppSpec(app);\n}\n\nexport function bindToServer(): TestClientBuilder {\n return new DefaultTestClientBuilder();\n}\n\nclass DefaultTestClient implements TestClient {\n readonly #connector: ClientHttpConnector;\n readonly #baseUrl?: string;\n constructor(connector: ClientHttpConnector,\n baseUrl: string | undefined,\n _builder: TestClientBuilder) {\n this.#connector = connector;\n this.#baseUrl = baseUrl;\n }\n\n fetch = async (input: string | URL, init?: RequestInit): Promise<Response> => {\n try {\n const method = init?.method as HttpMethod ?? 'GET';\n const uri = new URL(input, this.#baseUrl);\n const response = await this.#connector.connect(method, uri, async (request) => {\n // fetch Request to ClientHttpRequest\n const headers = new Headers(init?.headers);\n for (const [name, value] of headers.entries()) {\n request.headers.add(name, value);\n }\n let body = init?.body ?? Promise.resolve();\n if (body instanceof ReadableStream) {\n throw new Error(`Unsupported body type ${typeof init?.body} in fetch request`);\n }\n if (body instanceof FormData) {\n // Convert FormData to URLSearchParams\n const formDataEntries = Array.from(body.entries());\n body = new URLSearchParams();\n for (const [key, value] of formDataEntries) {\n body.append(key, value.toString());\n }\n }\n if (body instanceof URLSearchParams) {\n if (!request.headers.has('content-type')) {\n request.headers.set('content-type', 'application/x-www-form-urlencoded');\n }\n body = body.toString();\n }\n if (body instanceof Blob) {\n body = await body.bytes();\n }\n if (typeof body === 'string') {\n body = Buffer.from(body);\n }\n await request.body(body);\n\n\n });\n // ClientHttpResponse to fetch Response\n const headers = new Headers();\n for (const key of response.headers.keys()) {\n const value = response.headers.get(key);\n if (value !== undefined) {\n if (typeof value === 'string') {\n headers.set(key, value);\n } else if (Array.isArray(value)) {\n for (const v of value) {\n headers.append(key, v);\n }\n }\n }\n }\n const status = response.statusCode?.value;\n const body = await response.blob();\n return new Response(body, {status, headers});\n }\n catch (error) {\n return Response.error();\n }\n\n }\n}\n\nclass DefaultTestClientBuilder implements TestClientBuilder {\n readonly #httpHandlerBuilder?: Promise<WebHttpHandlerBuilder>;\n #connector?: ClientHttpConnector;\n #sslInfo?: SslInfo;\n #baseUrl: string = 'http://localhost:8080';\n\n constructor(httpHandlerBuilder?: Promise<WebHttpHandlerBuilder>, connector?: ClientHttpConnector, sslInfo?: SslInfo) {\n if (!(httpHandlerBuilder === undefined || connector === undefined)) {\n throw new Error('You can only set either httpHandlerBuilder or connector, not both.');\n }\n this.#connector = connector;\n this.#sslInfo = sslInfo;\n this.#httpHandlerBuilder = httpHandlerBuilder;\n }\n\n baseUrl(baseUrl: string): this {\n this.#baseUrl = baseUrl;\n return this;\n }\n\n clientConnector(connector: ClientHttpConnector): this {\n this.#connector = connector;\n return this;\n }\n\n async build(): Promise<TestClient> {\n let connector = this.#connector;\n if (connector === undefined) {\n if (this.#httpHandlerBuilder !== undefined) {\n connector = new HttpHandlerConnector((await this.#httpHandlerBuilder).build(), this.#sslInfo);\n }\n }\n connector ??= new FetchClientHttpConnector();\n\n return new DefaultTestClient(connector, this.#baseUrl, this);\n }\n}\n\nabstract class AbstractMockServerSpec implements MockServerSpec {\n #sslInfo?: SslInfo;\n #middleware: Middleware = [];\n\n middleware(...middleware: Middleware): this {\n this.#middleware = [...(this.#middleware), ...middleware];\n return this;\n }\n\n sslInfo(sslInfo?: SslInfo): this {\n this.#sslInfo = sslInfo;\n return this;\n }\n\n configureClient(): TestClientBuilder {\n const builder = this.initHttpHandlerBuilder(...this.#middleware);\n\n return new DefaultTestClientBuilder(builder, undefined, this.#sslInfo);\n }\n\n protected abstract initHttpHandlerBuilder(...middleware: Middleware): Promise<WebHttpHandlerBuilder>;\n\n async build(): Promise<TestClient> {\n return await this.configureClient().build();\n }\n}\n\nclass AppSpec extends AbstractMockServerSpec {\n readonly #app: ServerCustomizer;\n constructor(app: ServerCustomizer) {\n super();\n this.#app = app;\n }\n\n protected async initHttpHandlerBuilder(...middleware: Middleware) {\n const routes: RouteConfig = {\n middleware,\n corsConfig: {\n allowOrigin: ['http://localhost:8086']\n },\n resourcesConfig: {\n locations: []\n },\n cors: [],\n authConfig: {type: \"none\"},\n authorize: [],\n storage: new AsyncLocalStorage<{ exchange: ServerWebExchange }>(),\n sockets: new Map<string, SocketRoute>()\n };\n\n await configure(this.#app, {}, routes);\n const handler = { handle: compose(...routes.middleware) };\n return WebHttpHandlerBuilder.webHandler(handler);\n }\n}\n", "import type { Logger } from '@interopio/gateway/logging/api';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Middleware, ServerHttpRequest, ServerHttpResponse, ServerWebExchange } from '../../../types/web/server';\nimport { DefaultWebExchange } from '../../server/exchange.ts';\nimport type { HttpHeaders } from '../../../types/web/http';\nimport { HttpStatus } from '../../http/status.ts';\nimport getLogger from '../../logger.ts';\nimport { checkAndLogClientDisconnectedError } from '../util/client.ts';\nimport type { WebErrorHandler, WebFilter, WebHandler } from './types.ts';\nimport { ErrorHandlingWebHandler, FilteringWebHandler } from './handler.ts';\nimport type { HttpHandler } from '../../http/server/types.ts';\nimport { ServerCodecConfigurer } from '../../http/codec/types.ts';\nimport codecConfig from '../../http/codec/config.ts';\nimport { LoggingCodecSupport } from '../../http/codec/core.ts';\n\nclass HttpWebHandlerAdapter {\n\n readonly #logger: Logger;\n\n #codecConfigurer: ServerCodecConfigurer = undefined!;\n #enableLoggingRequestDetails: boolean = false;\n readonly #delegate: WebHandler;\n #storage?: AsyncLocalStorage<{ exchange: ServerWebExchange }>;\n\n constructor(logger: Logger, delegate: WebHandler) {\n this.#logger = logger;\n this.#delegate = delegate;\n }\n\n get codecConfigurer(): ServerCodecConfigurer {\n if (this.#codecConfigurer === undefined) {\n this.codecConfigurer = codecConfig.serverConfigurer.create()\n }\n return this.#codecConfigurer;\n }\n\n set codecConfigurer(configurer: ServerCodecConfigurer) {\n if (configurer === null || configurer === undefined) {\n throw new Error('codecConfigurer must not be null or undefined');\n }\n this.#codecConfigurer = configurer;\n\n this.#enableLoggingRequestDetails = false;\n for (const reader of this.#codecConfigurer.readers) {\n if (reader instanceof LoggingCodecSupport && reader.enableLoggingRequestDetails) {\n this.#enableLoggingRequestDetails = true;\n break;\n }\n }\n }\n\n protected createExchange(request: ServerHttpRequest, response: ServerHttpResponse): ServerWebExchange {\n const exchange = new DefaultWebExchange(request, response, this.codecConfigurer);\n return exchange;\n }\n\n set storage(storage: AsyncLocalStorage<{ exchange: ServerWebExchange }>) {\n this.#storage = storage;\n }\n\n\n formatHeaders(headers: HttpHeaders): string {\n let result = '{';\n\n for (const key of headers.keys()) {\n if (!this.#enableLoggingRequestDetails) {\n result += 'masked, ';\n break;\n }\n else {\n const value = headers.get(key);\n result += `\"${key}\": \"${value}\", `;\n }\n }\n if (result.endsWith(', ')) {\n result = result.slice(0, -2);\n }\n result += '}';\n return result;\n\n }\n\n formatRequest(request: ServerHttpRequest): string {\n const query = request.URL.search;\n return `HTTP ${request.method} \"${request.path}${query}`;\n }\n\n logRequest(exchange: ServerWebExchange) {\n if (this.#logger.enabledFor('debug')) {\n const trace = this.#logger.enabledFor('trace');\n this.#logger.debug(`${exchange.logPrefix}${this.formatRequest(exchange.request)}${trace ? `, headers: ${this.formatHeaders(exchange.request.headers)}` : ''}\"`);\n\n }\n }\n\n logResponse(exchange: ServerWebExchange) {\n if (this.#logger.enabledFor('debug')) {\n const trace = this.#logger.enabledFor('trace');\n const status = exchange.response.statusCode;\n this.#logger.debug(`${exchange.logPrefix}Completed ${status ?? '200 OK'}${trace ? `, headers: ${this.formatHeaders(exchange.response.headers)}` : ''}\"`);\n }\n }\n\n handleUnresolvedError(exchange: ServerWebExchange, error: Error) {\n const { request, response, logPrefix } = exchange;\n\n if (response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR)) {\n this.#logger.error(`${logPrefix}500 Server Error for ${this.formatRequest(request)}`, error);\n return;\n }\n else if (checkAndLogClientDisconnectedError(error, this.#logger)) {\n // todo notify observers\n return;\n }\n else {\n\n this.#logger.error(`${logPrefix}Error [${error.message} for ${this.formatRequest(request)}, but already ended (${response.statusCode})`, error);\n throw error;\n }\n\n }\n\n async web(exchange: ServerWebExchange): Promise<void> {\n return await this.#delegate.handle(exchange);\n }\n\n async http(request: ServerHttpRequest, response: ServerHttpResponse): Promise<void> {\n\n const exchange = this.createExchange(request, response);\n const callback = () => {\n this.logRequest(exchange);\n return this.web(exchange)\n .then(() => {\n this.logResponse(exchange);\n })\n .catch((error: Error) => {\n this.handleUnresolvedError(exchange, error)\n })\n .then(async () => {\n await exchange.response.end();\n });\n };\n\n await new Promise<void>((resolve, reject) => {\n if (this.#storage !== undefined) {\n this.#storage.run({ exchange }, () => {\n callback().then(() => resolve()).catch((error) => reject(error));\n });\n }\n else {\n callback().then(() => resolve()).catch((error) => reject(error));\n }\n });\n }\n}\n\nexport class WebHttpHandlerBuilder {\n readonly #webHandler: WebHandler;\n readonly #filters: WebFilter[] = [];\n readonly #exceptionHandlers: WebErrorHandler[] = [];\n readonly #middleware: Middleware = [];\n #handlerDecorator?: (handler: HttpHandler) => HttpHandler;\n #storage?: AsyncLocalStorage<{ exchange: ServerWebExchange }> = new AsyncLocalStorage();\n #codecConfigurer?: ServerCodecConfigurer;\n\n constructor(webHandler: WebHandler) {\n this.#webHandler = webHandler;\n }\n\n static webHandler(webHandler: WebHandler): WebHttpHandlerBuilder {\n return new WebHttpHandlerBuilder(webHandler);\n }\n\n filter(...filters: WebFilter[]): this {\n if (filters) {\n this.#filters.push(...filters);\n }\n return this;\n }\n\n middleware(consumer: (middleware: Middleware) => void): this {\n consumer(this.#middleware);\n return this;\n }\n\n exceptionHandler(...handlers: WebErrorHandler[]): this {\n if (handlers) {\n this.#exceptionHandlers.push(...handlers);\n }\n return this;\n }\n\n exceptionHandlers(consumer: (handlers: WebErrorHandler[]) => void): this {\n consumer(this.#exceptionHandlers);\n return this;\n }\n\n storage(storage: AsyncLocalStorage<{ exchange: ServerWebExchange }>): this {\n this.#storage = storage;\n return this;\n }\n\n codecConfigurer(configurer: ServerCodecConfigurer): this {\n this.#codecConfigurer = configurer;\n return this;\n }\n\n hasCodecConfigurer(): boolean {\n return this.#codecConfigurer !== undefined;\n }\n\n httpHandlerDecorator(decorator: (handler: HttpHandler) => HttpHandler): this {\n if (this.#handlerDecorator === undefined) {\n this.#handlerDecorator = decorator;\n }\n else {\n const previousDecorator = this.#handlerDecorator;\n this.#handlerDecorator = (handler: HttpHandler) => {\n handler = decorator(handler);\n handler = previousDecorator(handler);\n return handler;\n }\n }\n return this;\n }\n\n hasHttpHandlerDecorator(): boolean {\n return this.#handlerDecorator !== undefined;\n }\n\n build(): HttpHandler {\n const logger = getLogger('http');\n let decorated: WebHandler = new FilteringWebHandler(this.#webHandler, ...this.#filters);\n decorated = new ErrorHandlingWebHandler(decorated, ...this.#exceptionHandlers);\n\n const adapter = new HttpWebHandlerAdapter(logger, decorated);\n if (this.#storage !== undefined) adapter.storage = this.#storage;\n if (this.#codecConfigurer !== undefined) {\n adapter.codecConfigurer = this.#codecConfigurer;\n }\n const adapted: HttpHandler = async (request, response) => adapter.http(request, response);\n\n\n return this.#handlerDecorator ? this.#handlerDecorator(adapted) : adapted;\n }\n}\n", "import type { Logger } from '@interopio/gateway/logging/api';\n\nexport function isClientDisconnectedError(error: Error): boolean {\n if (error === null || error === undefined) {\n return false;\n }\n const { code, message } = error as any;\n return code === 'ECONNRESET' ||\n code === 'EPIPE' ||\n code === 'ERR_STREAM_PREMATURE_CLOSE' ||\n message?.toLowerCase().includes('client aborted') ||\n message?.toLowerCase().includes('socket hang up') ||\n message?.toLowerCase().includes('aborted');\n}\n\nexport function checkAndLogClientDisconnectedError(error: Error, logger: Logger): boolean {\n const isClientDisconnected = isClientDisconnectedError(error);\n if (isClientDisconnected) {\n if (logger.enabledFor('trace')) {\n logger.debug('looks like the client has gone away:', error);\n }\n else if (logger.enabledFor('debug')) {\n logger.debug(`looks like the client has gone away: ${error.message} (For full stack trace enable trace logging level.)`);\n }\n return true;\n }\n return false;\n}\n", "\nimport type { ServerWebExchange } from '../../../types/web/server';\nimport type { WebErrorHandler, WebFilter, WebFilterChain, WebHandler } from './types.ts';\n\nexport class WebHandlerDecorator implements WebHandler {\n readonly #delegate: WebHandler;\n\n constructor(delegate: WebHandler) {\n if (delegate === null || delegate === undefined) throw new Error('delegate must not be null or undefined');\n this.#delegate = delegate;\n }\n\n get delegate(): WebHandler {\n return this.#delegate;\n }\n\n async handle(exchange: ServerWebExchange): Promise<void> {\n return await this.#delegate.handle(exchange);\n }\n\n toString(): string {\n return `WebHandlerDecorator[delegate=${this.#delegate}]`;\n }\n}\n\nexport class ErrorHandlingWebHandler extends WebHandlerDecorator {\n readonly #errorHandlers: Array<WebErrorHandler>;\n constructor(delegate: WebHandler, ...errorHandlers: Array<WebErrorHandler>) {\n super(delegate);\n this.#errorHandlers = [... (errorHandlers)];\n Object.freeze(this.#errorHandlers);\n }\n\n get errorHandlers(): ReadonlyArray<WebErrorHandler> {\n return this.#errorHandlers;\n }\n\n handle(exchange: ServerWebExchange): Promise<void> {\n let completion: Promise<void>;\n try {\n completion = super.handle(exchange);\n }\n catch (e) {\n completion = Promise.reject(e);\n }\n\n // set handled web error attribute\n //exchange.attribute()\n for (const handler of this.#errorHandlers) {\n completion = completion.catch(async (reason) => {\n const error = reason instanceof Error ? reason : new Error(String(reason));\n await handler.handle(exchange, error);\n });\n }\n return completion;\n }\n}\n\nexport class DefaultWebFilterChain implements WebFilterChain {\n readonly #filters: WebFilter[];\n readonly #handler: WebHandler;\n\n /*readonly */ #current?: WebFilter;\n /*readonly */ #chian?: DefaultWebFilterChain;\n\n static of(handler: WebHandler, ...filters: WebFilter[]) {\n const allFilters = [...filters];\n const result = new DefaultWebFilterChain(filters, handler);\n const chain = DefaultWebFilterChain.initChain(filters, handler);\n result.#current = chain.#current;\n result.#chian = chain.#chian;\n return result;\n }\n\n private static initChain(filters: WebFilter[], handler: WebHandler): DefaultWebFilterChain {\n let chain = new DefaultWebFilterChain(filters, handler, undefined, undefined);\n for (const current of [...filters].reverse()) {\n chain = new DefaultWebFilterChain(filters, handler, current, chain);\n }\n return chain;\n }\n\n private constructor(filters: WebFilter[], handler: WebHandler, current? : WebFilter, chain?: DefaultWebFilterChain) {\n this.#filters = filters;\n this.#handler = handler;\n this.#current = current;\n this.#chian = chain;\n }\n\n get filters(): ReadonlyArray<WebFilter> {\n return this.#filters;\n }\n\n get handler(): WebHandler {\n return this.#handler;\n }\n\n async filter(exchange: ServerWebExchange): Promise<void> {\n if (this.#current !== undefined && this.#chian !== undefined) {\n await this.#invokeFilter(this.#current, this.#chian, exchange);\n }\n else {\n await this.#handler.handle(exchange);\n }\n }\n\n #invokeFilter(filter: WebFilter, chain: DefaultWebFilterChain, exchange: ServerWebExchange): Promise<void> {\n return filter.filter(exchange, chain);\n }\n}\n\nexport class FilteringWebHandler extends WebHandlerDecorator {\n readonly #chain: DefaultWebFilterChain;\n\n constructor(handler: WebHandler, ...filters: Array<WebFilter>) {\n super(handler);\n this.#chain = DefaultWebFilterChain.of(handler, ...(filters));\n }\n\n get filters() {\n return this.#chain.filters;\n }\n\n handle(exchange: ServerWebExchange): Promise<void> {\n return this.#chain.filter(exchange);\n }\n}\n", "import { bindToApp, bindToServer } from './server/client.ts';\n\nexport const TestClient = {\n bindToApp: bindToApp,\n bindToServer: bindToServer\n}\n"],
5
+ "mappings": "AACA,OAA2B,QAAAA,OAAY,WACvC,OAAS,UAAAC,OAAc,eAEvB,SAASC,GAAUC,EAAsBC,EAA0C,CAC/E,IAAIC,EAAOF,EAAQ,IAAI,kBAAkB,EAIzC,GAHI,MAAM,QAAQE,CAAI,IAClBA,EAAOA,EAAK,CAAC,GAEbA,EAAM,CACN,IAAMC,EAAOH,EAAQ,IAAI,kBAAkB,EACvCG,IACAD,EAAO,GAAGA,CAAI,IAAIC,CAAI,GAE9B,CAKA,OAJAD,IAASF,EAAQ,IAAI,MAAM,EACvB,MAAM,QAAQE,CAAI,IAClBA,EAAOA,EAAK,CAAC,GAEbA,EACQA,EAAgB,MAAM,IAAK,CAAC,EAAE,CAAC,EAAE,KAAK,EAG3CD,CACX,CAEA,SAASG,GAAeJ,EAA+B,CACnD,IAAMK,EAAIL,EAAQ,IAAI,iBAAiB,EACvC,OAAQ,OAAOK,GAAM,UAAcA,EAAE,YAAY,IAAM,IAC3D,CAEA,SAASC,GAAcN,EAAsBO,EAAiC,CAC1E,IAAIC,EAAQR,EAAQ,IAAI,mBAAmB,EAK3C,OAHI,MAAM,QAAQQ,CAAK,IACnBA,EAAQA,EAAM,CAAC,GAEfA,IAAU,OACFA,EAAiB,MAAM,IAAK,CAAC,EAAE,CAAC,EAAE,KAAK,EAE1CJ,GAAeJ,CAAO,EACpB,QAEJO,CACX,CAEA,SAASE,GAAmBC,EAAUV,EAAsBW,EAAuD,CAC/G,IAAMR,EAAOQ,EAAgBA,EAAc,KAAoBD,EAAI,WAAjB,SAA4B,IAAM,GAEhFR,EAAOF,EAAQ,IAAI,iBAAiB,EAIxC,GAHI,MAAM,QAAQE,CAAI,IAClBA,EAAOA,EAAK,CAAC,GAEbA,IAAS,OACT,OAAAA,EAAQA,EAAgB,MAAM,IAAK,CAAC,EAAE,CAAC,EAAE,KAAK,EACvC,CAAE,QAASA,EAAM,KAAM,OAAOC,CAAI,EAAG,OAAQN,GAAKK,CAAI,IAAM,EAAI,OAAS,MAAO,CAE/F,CAEO,IAAeU,EAAf,KAA8E,CACxEC,GACC,YAAYb,EAAkB,CACpC,KAAKa,GAAWb,CACpB,CACA,IAAI,SAAmB,CACnB,OAAO,KAAKa,EAChB,CACJ,EAEsBC,EAAf,MAAeC,UAAuEH,CAA6B,CACtH,OAAe,aAAe,EAC9BI,GAEA,IAAI,IAAa,CACb,OAAI,KAAKA,KAAQ,SACb,KAAKA,GAAM,GAAG,KAAK,OAAO,CAAC,IAAI,EAAED,EAAoB,YAAY,IAG9D,KAAKC,EAChB,CAEU,QAAiB,CACvB,MAAO,SACX,CAEA,IAAI,SAAwB,CACxB,OAAOC,GAAa,KAAK,OAAO,CACpC,CAEU,UAAUhB,EAA0C,CAC1D,OAAOF,GAAU,KAAK,QAASE,CAAW,CAC9C,CAEU,cAAcM,EAAiC,CACrD,OAAOD,GAAc,KAAK,QAASC,CAAe,CACtD,CAIU,mBAAmBI,EAA6B,CACtD,OAAOF,GAAmB,KAAK,IAAK,KAAK,QAASE,CAAa,CACnE,CACJ,EAEsBO,EAAf,cAAuFN,CAA6B,CACvH,IAAI,SAA4B,CAC5B,OAAOO,GAAqB,KAAK,OAAO,CAC5C,CAEU,eAAeC,EAAwC,CAW7D,OAVe,IAAItB,GAAO,CACtB,IAAKsB,EAAe,KACpB,MAAOA,EAAe,MACtB,OAAQA,EAAe,OACvB,OAAQA,EAAe,OACvB,KAAMA,EAAe,KACrB,OAAQA,EAAe,OACvB,SAAUA,EAAe,SACzB,SAAUA,EAAe,QAC7B,CAAC,EACa,SAAS,CAC3B,CAEJ,EAEA,SAASH,GAAajB,EAAoC,CACtD,OAAOA,EAAQ,KAAK,QAAQ,EACvB,IAAIqB,GAAKA,EAAE,MAAM,GAAG,EAAE,IAAKC,GAAOxB,GAAO,MAAMwB,CAAE,CAAC,CAAC,EACnD,KAAK,CAAC,EACN,OAAQC,GAAOA,IAAO,MAAS,EAC/B,IAAKA,GACyB,OAAO,OAAO,CAAC,KAAMA,EAAG,IAAK,MAAOA,EAAG,KAAK,CAAC,CAE3E,CACT,CAIA,SAASJ,GAAqBnB,EAAwC,CAClE,OAAOA,EAAQ,KAAK,YAAY,EAAE,IAAKwB,GAAW,CAC9C,IAAMC,EAAS3B,GAAO,MAAM0B,CAAM,EAClC,GAAIC,EAAQ,CACR,IAAMC,EAAkC,CAAC,KAAMD,EAAO,IAAK,MAAOA,EAAO,MAAO,OAAQ,OAAOA,EAAO,QAAU,EAAE,CAAC,EACnH,OAAIA,EAAO,WAAUC,EAAO,SAAW,IACnCD,EAAO,SAAQC,EAAO,OAASD,EAAO,QACtCA,EAAO,OAAMC,EAAO,KAAOD,EAAO,MAClCA,EAAO,SAAQC,EAAO,OAAS,IAC/BD,EAAO,WAAUC,EAAO,SAAW,IACnCD,EAAO,WAAUC,EAAO,SAAWD,EAAO,UACvC,OAAO,OAAOC,CAAM,CAC/B,CACJ,CAAC,EAAE,OAAQF,GAAqCA,IAAW,MAAS,CACxE,CCvJA,OAAS,YAAAG,OAAgB,YCDzB,OAAS,YAAAC,OAAgB,YAElB,IAAMC,EAAgB,IAChBC,GAAM,IAAIF,GAAS,GAAGC,CAAa,IAAIA,CAAa,EAAE,EACtDE,GAAiC,2BACjCC,GAA2B,IAAIJ,GAASG,EAA8B,EAE5E,SAASE,EAAeC,EAA6B,CACxD,OAAOA,EAAS,OAASL,CAC7B,CAEO,SAASM,EAAkBD,EAA6B,CAC3D,OAAOA,EAAS,UAAYL,GAAiBK,EAAS,QAAQ,WAAW,GAAGL,CAAa,GAAG,CAChG,CAEO,SAASO,GAAWF,EAA6B,CACpD,MAAO,CAACD,EAAeC,CAAQ,GAAK,CAACC,EAAkBD,CAAQ,CACnE,CAGO,IAAMG,EAAN,cAAmC,KAAM,CACnC,SACT,YAAYH,EAAkBI,EAAkBC,EAAwB,CACpE,MAAMD,IAAY,OAAY,sBAAsBJ,CAAQ,IAAM,sBAAsBA,CAAQ,MAAMI,CAAO,GAAIC,CAAO,EACxH,KAAK,SAAWL,CACpB,CACJ,EAEO,SAASM,GAAeC,EAAcC,EAAiBC,EAA4B,CACtF,IAAMC,EAAQ,GAAGH,CAAI,IAAIC,CAAO,GAC5BG,EACJ,GAAI,CACAA,EAAS,IAAIjB,GAASgB,CAAK,CAC/B,OACOE,EAAO,CACV,MAAM,IAAIT,EAAqBO,EAAO,OAAY,CAAE,MAAOE,CAAM,CAAE,CACvE,CACA,OAAIH,GACAE,EAAO,OAAO,IAAI,UAAWF,CAAO,EAEjCE,CACX,CAEO,SAASE,GAAiBb,EAAmC,CAChE,IAAMc,EAAcd,EAAS,QAAQ,YAAY,GAAG,EACpD,OAAIc,IAAgB,IAAMA,EAAcd,EAAS,QAAQ,OAC9CA,EAAS,QAAQ,UAAUc,EAAc,CAAC,EAE9C,IAEX,CAEO,SAASC,EAAiBC,EAAaC,EAAuB,CACjE,GAAI,CAACA,EACD,MAAO,GAGX,GAAIlB,EAAeiB,CAAC,GAAKjB,EAAekB,CAAC,EACrC,MAAO,GAGN,GAAID,EAAE,OAASC,EAAE,KAAM,CACxB,GAAID,EAAE,UAAYC,EAAE,QAChB,MAAO,GAEX,GAAIhB,EAAkBe,CAAC,GAAKf,EAAkBgB,CAAC,EAAG,CAC9C,IAAMC,EAAUL,GAAiBG,CAAC,EAC5BG,EAAUN,GAAiBI,CAAC,EAClC,GAAID,EAAE,UAAYrB,GAAiBsB,EAAE,UAAYtB,EAC7C,MAAO,GAEN,GAAIM,EAAkBe,CAAC,GAAKG,IAAY,KACzC,OAAOD,IAAYD,EAAE,SAAWC,IAAYC,EAE3C,GAAIlB,EAAkBgB,CAAC,GAAKC,IAAY,KACzC,OAAOF,EAAE,UAAYG,GAAWA,IAAYD,CAEpD,CACJ,CACA,MAAO,EACX,CDvEA,IAAME,GAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYLC,EAAN,MAAMC,UAAkBC,EAAS,CACpC,OAAgB,IAAiB,IAAID,EAAU,KAAK,EACpD,OAAgB,yBAAsC,IAAIA,EAAUE,EAA8B,EAClG,OAAgB,iBAA8B,IAAIF,EAAU,kBAAkB,EAC9E,OAAgB,mBAAgC,IAAIA,EAAU,sBAAsB,EAEpF,OAAgB,oBAAiC,IAAIA,EAAU,qBAAqB,EAEpF,OAAgB,WAAwB,IAAIA,EAAU,YAAY,EAClE,OAAgB,UAAuB,IAAIA,EAAU,WAAW,EAEhE,MAAgBG,GAAwB,IAEhC,YAAYC,EAAe,CAC/B,MAAMA,CAAK,EACX,KAAKC,GAAY,KAAK,IAAI,EAC1B,KAAKA,GAAY,KAAK,OAAO,EAC7B,OAAW,CAACC,EAAKC,CAAK,IAAK,KAAK,OAC5B,KAAK,gBAAgBD,EAAKC,CAAK,CAEvC,CAEU,gBAAgBD,EAAaC,EAAe,CAKlD,GAJA,KAAKF,GAAYC,CAAG,EACfE,GAASD,CAAK,GACf,KAAKF,GAAYE,CAAK,EAEtBD,IAAQN,EAAUG,GAAuB,CACzC,IAAMM,EAAgBC,GAAQH,CAAK,EAC7BI,EAAI,WAAWF,CAAa,EAClC,GAAI,MAAME,CAAC,GAAKA,EAAI,GAAOA,EAAI,EAC3B,MAAM,IAAIC,EAAsB,0BAA0BL,CAAK,EAAE,CAEzE,CACJ,CAEAF,GAAYQ,EAAe,CACvB,QAASC,EAAI,EAAGA,EAAID,EAAM,OAAQC,IAAK,CACnC,IAAMC,EAAIF,EAAM,WAAWC,CAAC,EAC5B,GAAIC,EAAI,IACDA,EAAI,KACJA,IAAM,IACNA,IAAM,IACNA,IAAM,IACNA,IAAM,IACNA,IAAM,IACNA,IAAM,IACNA,IAAM,IACNA,IAAM,IACNA,IAAM,IACNA,IAAM,IACNA,IAAM,IACNA,IAAM,IACNA,IAAM,IACNA,IAAM,IACNA,IAAM,IACNA,IAAM,KACNA,IAAM,KACNA,IAAM,IACNA,IAAM,EAET,MAAM,IAAIH,EAAsB,kBAAkBC,CAAK,EAAE,CAEjE,CACJ,CAGA,IAAI,SAAkB,CAClB,IAAMG,EAAgB,KAAK,OAAO,IAAIhB,EAAUG,EAAqB,EACrE,OAAQa,IAAkB,KAAQ,WAAWN,GAAQM,CAAa,CAAC,EAAI,CAC3E,CAEA,OAAO,eAAeZ,EAA0B,CAC5C,OAAO,IAAIJ,EAAUI,CAAK,CAC9B,CAEA,OAAO,oBAAoBa,EAAiC,CACxD,OAAKA,GAAY,KAAK,EAGfA,EAAW,MAAM,GAAG,EACtB,IAAIC,GAAQA,EAAK,KAAK,CAAC,EACvB,OAAOA,GAAQA,EAAK,OAAS,CAAC,EAC9B,IAAIA,GAAQlB,EAAU,eAAekB,CAAI,CAAC,EALpC,CAAC,CAMhB,CAEA,OAAO,mBAAmBD,EAAmC,CACzD,OAAKA,EAGIA,EAAW,SAAW,EACpBjB,EAAU,oBAAoBiB,EAAW,CAAC,CAAC,EAG3CA,EAAW,QAAQE,GAAanB,EAAU,oBAAoBmB,CAAS,CAAC,EANxE,CAAC,CAQhB,CAEA,OAAO,YAAYC,EAA+B,CAC9C,OAAIA,aAAoBpB,EACboB,EAEJ,IAAIpB,EAAUoB,EAAS,SAAS,CAAC,CAC5C,CAEA,OAAO,gBAAgBtB,EAAoC,CACvD,OAAOA,EAAU,IAAIsB,GAAYpB,EAAU,YAAYoB,CAAQ,CAAC,CACpE,CACJ,EAEaR,EAAN,cAAoC,KAAM,CAC7C,YAAYS,EAAiB,CACzB,MAAMA,CAAO,CACjB,CACJ,EAEMC,IAAuD,UAAoD,CAC7G,IAAMC,EAAM,IAAI,IAEhB,QAAWC,KAAQ1B,GAAU,KAAK,EAAE,MAAM;AAAA,CAAI,EAAG,CAC7C,IAAM2B,EAAUD,EAAK,KAAK,EAC1B,GAAI,CAACC,GAAWA,EAAQ,WAAW,GAAG,EAAG,SAEzC,IAAMC,EAAQD,EAAQ,MAAM,KAAK,EACjC,GAAIC,EAAM,OAAS,EAAG,SAEtB,GAAM,CAACN,EAAU,GAAGO,CAAU,EAAID,EAC5BP,EAAYpB,EAAU,eAAeqB,CAAQ,EAEnD,QAAWQ,KAAOD,EAAY,CAC1B,IAAMrB,EAAM,IAAMsB,EAAI,YAAY,EAC5BC,EAAWN,EAAI,IAAIjB,CAAG,EACxBuB,EACAA,EAAS,KAAKV,CAAS,EAGvBI,EAAI,IAAIjB,EAAK,CAACa,CAAS,CAAC,CAEhC,CACJ,CAEA,OAAOI,CACX,GAAG,EAeH,SAASO,GAASC,EAAoB,CAClC,OAAOA,EAAE,QAAU,IACdA,EAAE,WAAW,GAAG,GAAKA,EAAE,SAAS,GAAG,GACnCA,EAAE,WAAW,GAAG,GAAKA,EAAE,SAAS,GAAG,EAC5C,CAEA,SAASC,GAAQD,EAAW,CACxB,OAAID,GAASC,CAAC,EACHA,EAAE,UAAU,EAAGA,EAAE,OAAS,CAAC,EAE/BA,CACX,CErLA,SAASE,GAAYC,EAAyB,CAC1C,IAAMC,EAAiB,CAAC,EACxB,CACI,IAAIC,EAAQ,EACRC,EAAM,EAEV,QAASC,EAAI,EAAGA,EAAIJ,EAAM,OAAQI,IAC9B,OAAQJ,EAAM,WAAWI,CAAC,EAAG,CACzB,IAAK,IACGF,IAAUC,IACVD,EAAQC,EAAMC,EAAI,GAEtB,MACJ,IAAK,IACDH,EAAK,KAAKD,EAAM,MAAME,EAAOC,CAAG,CAAC,EACjCD,EAAQC,EAAMC,EAAI,EAClB,MACJ,QACID,EAAMA,EAAM,EACZ,KACR,CAEJF,EAAK,KAAKD,EAAM,MAAME,EAAOC,CAAG,CAAC,CACrC,CAEA,OAAOF,CACX,CAEA,SAASI,GAAOC,EAAqE,CAC7E,OAAOA,GAAW,WAClBA,EAAS,CAACA,CAAM,GAEhB,OAAOA,GAAW,WAClBA,EAAS,CAAC,OAAOA,CAAM,CAAC,GAE5B,IAAML,EAAiB,CAAC,EACxB,GAAIK,EACA,QAAWN,KAASM,EACZN,GACAC,EAAK,KAAK,GAAGF,GAAYC,CAAK,CAAC,EAI3C,OAAOC,CACX,CAcO,IAAMM,EAAN,cAA6B,GAA+D,CAE/F,IAAIC,EAAc,CACd,OAAO,MAAM,IAAIA,EAAK,YAAY,CAAC,CACvC,CAEA,IAAIA,EAAkC,CAClC,OAAO,KAAK,IAAIA,CAAI,IAAI,CAAC,CAC7B,CAEA,KAAKA,EAAc,CACf,IAAMC,EAAS,MAAM,IAAID,EAAK,YAAY,CAAC,EAC3C,OAAOE,GAAOD,CAAM,CACxB,CAEA,IAAID,EAAcG,EAAgE,CAO9E,OANI,OAAOA,GAAU,WACjBA,EAAQ,OAAOA,CAAK,GAEpB,OAAOA,GAAU,WACjBA,EAAQ,CAACA,CAAK,GAEdA,EACO,MAAM,IAAIH,EAAK,YAAY,EAAGG,CAAK,GAG1C,MAAM,OAAOH,EAAK,YAAY,CAAC,EACxB,KAEf,CAEA,IAAIA,EAAcG,EAAqC,CACnD,IAAMC,EAAO,MAAM,IAAIJ,EAAK,YAAY,CAAC,EACzC,OAAI,OAAOG,GAAU,WACjBA,EAAQ,CAACA,CAAK,GAEdC,IACAD,EAAQC,EAAK,OAAOD,CAAK,GAE7B,KAAK,IAAIH,EAAMG,CAAK,EACb,IACX,CACJ,EAEaE,GAA0C,IAAIN,EAGpD,SAASO,GAAeC,EAA6C,CACxE,IAAMJ,EAAQI,EAAQ,IAAI,cAAc,EACxC,OAAOJ,EAAQK,EAAU,eAAeL,CAAe,EAAI,MAE/D,CC3GO,IAAeM,EAAf,cAAiDC,CAAyC,CAEnF,YAAYC,EAAoBC,EAAU,CAChD,MAAM,IAAIC,CAAgB,EAC1B,KAAK,IAAMD,EACX,KAAK,OAASD,CAClB,CAES,IACA,MACb,EAEsBG,EAAf,cAAkDC,CAA0C,CACrF,YAAYC,EAA4BC,EAA8B,CAC5E,MAAMA,CAAO,EACb,KAAK,WAAaD,CACtB,CACS,UACb,EC1BA,IAAME,GAAN,KAAsD,CACzCC,GACT,YAAYC,EAAe,CACvB,KAAKD,GAASC,CAClB,CACA,IAAI,OAAgB,CAChB,OAAO,KAAKD,EAChB,CAEA,UAAmB,CACf,OAAO,KAAKA,GAAO,SAAS,CAChC,CACJ,EAEaE,EAAN,MAAMC,CAAqC,CAC9C,OAAgB,SAAW,IAAIA,EAAW,IAAK,UAAU,EACzD,OAAgB,oBAAsB,IAAIA,EAAW,IAAK,qBAAqB,EAI/E,OAAgB,GAAK,IAAIA,EAAW,IAAK,IAAI,EAC7C,OAAgB,QAAU,IAAIA,EAAW,IAAK,SAAS,EACvD,OAAgB,SAAW,IAAIA,EAAW,IAAK,UAAU,EACzD,OAAiB,8BAAgC,IAAIA,EAAW,IAAK,+BAA+B,EACpG,OAAgB,WAAa,IAAIA,EAAW,IAAK,YAAY,EAC7D,OAAgB,cAAgB,IAAIA,EAAW,IAAK,eAAe,EACnE,OAAgB,gBAAkB,IAAIA,EAAW,IAAK,iBAAiB,EACvE,OAAgB,aAAe,IAAIA,EAAW,IAAK,cAAc,EAEjE,OAAgB,QAAU,IAAIA,EAAW,IAAK,SAAS,EAIvD,OAAgB,iBAAmB,IAAIA,EAAW,IAAK,kBAAkB,EACzE,OAAgB,kBAAoB,IAAIA,EAAW,IAAK,mBAAmB,EAI3E,OAAgB,YAAc,IAAIA,EAAW,IAAK,aAAa,EAC/D,OAAgB,aAAe,IAAIA,EAAW,IAAK,cAAc,EACjE,OAAgB,UAAY,IAAIA,EAAW,IAAK,WAAW,EAC3D,OAAgB,UAAY,IAAIA,EAAW,IAAK,WAAW,EAC3D,OAAgB,mBAAqB,IAAIA,EAAW,IAAK,oBAAoB,EAC7E,OAAgB,eAAiB,IAAIA,EAAW,IAAK,gBAAgB,EACrE,OAAgB,8BAAgC,IAAIA,EAAW,IAAK,+BAA+B,EACnG,OAAgB,gBAAkB,IAAIA,EAAW,IAAK,iBAAiB,EACvE,OAAgB,SAAW,IAAIA,EAAW,IAAK,UAAU,EACzD,OAAgB,KAAO,IAAIA,EAAW,IAAK,MAAM,EACjD,OAAgB,gBAAkB,IAAIA,EAAW,IAAK,iBAAiB,EACvE,OAAgB,oBAAsB,IAAIA,EAAW,IAAK,qBAAqB,EAC/E,OAAgB,kBAAoB,IAAIA,EAAW,IAAK,mBAAmB,EAC3E,OAAgB,aAAe,IAAIA,EAAW,IAAK,cAAc,EACjE,OAAgB,uBAAyB,IAAIA,EAAW,IAAK,wBAAwB,EAErF,OAAgB,mBAAqB,IAAIA,EAAW,IAAK,oBAAoB,EAC7E,OAAgB,YAAc,IAAIA,EAAW,IAAK,cAAe,EAEjE,OAAgB,UAAY,IAAIA,EAAW,IAAK,WAAW,EAC3D,OAAgB,iBAAmB,IAAIA,EAAW,IAAK,kBAAkB,EACzE,OAAgB,sBAAwB,IAAIA,EAAW,IAAK,uBAAuB,EACnF,OAAgB,kBAAoB,IAAIA,EAAW,IAAK,mBAAmB,EAC3E,OAAgB,gCAAkC,IAAIA,EAAW,IAAK,iCAAiC,EACvG,OAAgB,8BAAgC,IAAIA,EAAW,IAAK,+BAA+B,EAGnG,OAAgB,sBAAwB,IAAIA,EAAW,IAAK,uBAAuB,EACnF,OAAgB,gBAAkB,IAAIA,EAAW,IAAK,iBAAiB,EACvE,OAAgB,YAAc,IAAIA,EAAW,IAAK,aAAa,EAC/D,OAAgB,oBAAsB,IAAIA,EAAW,IAAK,qBAAqB,EAC/E,OAAgB,gBAAkB,IAAIA,EAAW,IAAK,iBAAiB,EACvE,OAAgB,2BAA6B,IAAIA,EAAW,IAAK,4BAA4B,EAC7F,OAAgB,wBAA0B,IAAIA,EAAW,IAAK,yBAAyB,EACvF,OAAgB,qBAAuB,IAAIA,EAAW,IAAK,sBAAsB,EACjF,OAAgB,cAAgB,IAAIA,EAAW,IAAK,eAAe,EACnE,OAAgB,aAAe,IAAIA,EAAW,IAAK,cAAc,EACjE,OAAgB,gCAAkC,IAAIA,EAAW,IAAK,iCAAiC,EAEvG,MAAgBC,GAAwB,CAAC,EACzC,MAAO,CACH,OAAO,KAAKD,CAAU,EACjB,OAAOE,GAAOA,IAAQ,UAAYA,IAAQ,SAAS,EACnD,QAAQA,GAAO,CACZ,IAAMJ,EAAQE,EAAWE,CAAG,EACxBJ,aAAiBE,IACjB,OAAO,eAAeF,EAAO,OAAQ,CAAE,WAAY,GAAM,MAAOI,EAAK,SAAU,EAAM,CAAC,EACtFF,EAAWC,GAAQ,KAAKH,CAAK,EAErC,CAAC,CAET,CAEA,OAAO,QAAQK,EAAsC,CACjD,QAAWC,KAAUJ,EAAWC,GAC5B,GAAIG,EAAO,QAAUD,EACjB,OAAOC,CAGnB,CAESP,GACAQ,GAED,YAAYP,EAAeQ,EAAgB,CAC/C,KAAKT,GAASC,EACd,KAAKO,GAAUC,CACnB,CAEA,IAAI,OAAgB,CAChB,OAAO,KAAKT,EAChB,CACA,IAAI,QAAiB,CACjB,OAAO,KAAKQ,EAChB,CAEA,UAAW,CACP,MAAO,GAAG,KAAKR,EAAM,IAAI,KAAK,IAAO,EACzC,CACJ,EAGO,SAASU,EAAeT,EAAgD,CAC3E,GAAI,OAAOA,GAAU,SAAU,CAC3B,GAAIA,EAAQ,KAAOA,EAAQ,IACvB,MAAM,IAAI,MAAM,eAAeA,CAAK,6BAA6B,EAErE,IAAMM,EAASL,EAAW,QAAQD,CAAK,EACvC,OAAIM,IAAW,OACJA,EAEJ,IAAIR,GAAsBE,CAAK,CAC1C,CACA,OAAOA,CACX,CCxHA,IAAMU,GAAN,cAAqCC,CAAuD,CACxFC,GACA,YAAYC,EAAoBC,EAAU,CACtC,MAAMD,EAAQC,CAAG,CACrB,CAEA,MAAM,KAAKC,EAAoF,CAC3F,YAAKH,GAAQG,aAAgB,eAAiBA,EAAO,MAAMA,EACpD,MAAM,KAAK,IAAI,CAC1B,CAEA,KAAM,CACF,OAAO,QAAQ,QAAQ,EAAI,CAC/B,CAEA,kBAAyB,CACrB,IAAMF,EAAS,KAAK,OACdG,EAAU,IAAI,QACpB,QAAWC,KAAO,KAAK,QAAQ,KAAK,EAChC,GAAIA,EAAI,YAAY,IAAM,iBAG1B,QAAWC,KAAS,KAAK,QAAQ,KAAKD,CAAG,EACrCD,EAAQ,OAAOC,EAAKC,CAAK,EAG5B,KAAK,QAAQ,IAAI,QAAQ,GAC1BF,EAAQ,OAAO,SAAU,KAAK,EAElC,IAAMD,EAAO,KAAKH,GAElB,OAAO,IAAI,QAAQ,KAAK,IAAK,CAAC,OAAAC,EAAQ,QAAAG,EAAS,KAAAD,CAAI,CAAC,CACxD,CACJ,EACA,SAASI,GAAcH,EAAkC,CACrD,IAAMI,EAAS,IAAIC,EACnB,OAAW,CAACJ,EAAKC,CAAK,IAAKF,EAAQ,QAAQ,EACvCI,EAAO,IAAIH,EAAKC,CAAK,EAEzB,OAAOE,CACX,CACA,IAAME,GAAN,cAAsCC,CAAyD,CAC3FC,GACA,YAAYC,EAAoB,CAC5B,MAAMC,EAAeD,EAAS,MAAM,EAAGN,GAAcM,EAAS,OAAO,CAAC,EACtE,KAAKD,GAAYC,CACrB,CAEA,IAAI,eAAgB,CAChB,OAAO,KAAKD,GAAU,UAC1B,CAEA,IAAI,MAAO,CACP,OAAO,KAAKA,GAAU,MAAQ,MAClC,CAEA,MAAO,CACH,OAAO,KAAKA,GAAU,KAAK,CAC/B,CACJ,EAEaG,EAAN,KAA8D,CACxDC,GACT,YAAYC,EAAwB,WAAW,MAAO,CAClD,KAAKD,GAASC,CAClB,CAEA,MAAM,QAAQhB,EAAoBC,EAAUgB,EAA6F,CACrI,IAAMC,EAAyB,IAAIrB,GAAuBG,EAAQC,CAAG,EACrE,MAAMgB,EAAgBC,CAAsB,EAC5C,IAAMC,EAAeD,EAAuB,iBAA0B,EAChEE,EAAgB,MAAM,KAAKL,GAAOI,CAAY,EACpD,OAAO,IAAIV,GAAwBW,CAAa,CACpD,CACJ,EC3EA,UAAYC,MAAY,kBAEjB,IAAMC,EAAN,cAAoCC,CAAuD,CAC9FC,GACAC,GAAyC,IAAM,CAC3C,MAAM,IAAI,MAAM,cAAc,CAClC,EACA,YAAYC,EAAUC,EAAoB,CACtC,MAAMA,EAAQD,CAAG,EACjB,KAAKF,GAAgB,MAAOI,GAAS,CACjC,IAAMC,EAAsB,CAAC,EAC7B,KAAKJ,GAAQ,IACK,iBAAe,KAAKI,CAAM,EAE5C,IAAMC,EAASF,EAAK,UAAU,EAC1BG,EACJ,EAAG,CACC,GAAM,CAAC,MAAAC,EAAO,KAAMC,CAAW,EAAI,MAAMH,EAAO,KAAK,EACrDC,EAAOE,EACHD,IAAU,QACVH,EAAO,KAAKG,CAAK,CAEzB,OAAS,CAACD,GACV,MAAO,EACX,CACJ,CACA,IAAI,aAAaG,EAAgE,CAC7E,KAAKV,GAAgBU,CACzB,CAEA,kBAAyB,CACrB,OAAO,IACX,CAEA,SAAqC,CACjC,OAAO,KAAKT,GAAM,CACtB,CAEA,KAAKG,EAA2F,CAC5F,IAAMO,GAAiB,iBAAmB,CACtC,GAAIP,aAAgB,eAAgB,CAChC,IAAME,EAASF,EAAK,UAAU,EAC1BG,EACJ,EAAG,CACC,GAAM,CAAC,MAAAC,EAAO,KAAMC,CAAW,EAAI,MAAMH,EAAO,KAAK,EACrDC,EAAOE,EACHD,IAAU,SACV,MAAMA,EAEd,OAAS,CAACD,EACd,KACK,CACD,IAAMC,EAAQ,MAAMJ,EAChBI,IAAU,SACV,MAAMA,EAEd,CAEJ,GAAG,EACH,OAAO,KAAKR,GAAqB,iBAAe,KAAKW,CAAa,CAA8B,CACpG,CAEA,MAAM,KAAM,CACR,OAAO,MAAM,KAAK,KAAK,QAAQ,QAAQ,CAAC,CAC5C,CAEJ,EAEaC,EAAN,cAAqCC,CAAwE,CAChHC,GACAb,GAA0C,iBAAe,KAAK,CAAC,CAAC,EAChE,YAAYc,EAAiC,CACzC,MAAM,IAAIC,CAAgB,EAC1B,KAAKF,GAAcG,EAAeF,CAAM,CAC5C,CAEA,IAAI,YAA6B,CAC7B,OAAO,KAAKD,EAChB,CAEA,UAAUI,EAAcV,EAA2C,CAC/D,OAAC,KAAK,QAA+B,IAAIU,EAAMV,CAAK,EAC7C,IACX,CAEA,UAAUU,EAAcV,EAAkC,CACtD,OAAC,KAAK,QAA+B,IAAIU,EAAMV,CAAK,EAC7C,IACX,CAEA,QAAQJ,EAAce,EAAgC,CAClD,YAAKlB,GAAe,iBAAe,KAAK,CAAC,OAAO,KAAKG,EAAMe,CAAO,CAAC,CAAC,EAC7D,IACX,CAEA,IAAI,KAAKf,EAAiC,CACtC,KAAKH,GAAQG,CACjB,CAEA,IAAI,MAAO,CACP,OAAO,KAAKH,EAChB,CAEA,MAAM,MAAO,CACT,IAAMI,EAAsB,CAAC,EAC7B,GAAI,KAAK,OAAS,OACd,cAAiBe,KAAS,KAAK,KAC3Bf,EAAO,KAAKe,CAAK,EAGzB,OAAO,IAAI,KAAKf,EAAQ,CAAC,KAAM,KAAK,QAAQ,IAAI,cAAc,GAAe,0BAA0B,CAAC,CAC5G,CACJ,ECpGA,OAAOgB,OAAU,YCvBV,SAASC,GAAQC,EAA0BC,EAAeC,EAA6B,CAC1F,IAAMC,EAAWH,EAAU,SAE3B,GADAE,EAAMA,GAAOC,EAAS,OAClBF,IAAU,GAAKC,IAAQC,EAAS,OAChC,OAAOH,EAEX,GAAIC,IAAUC,EACV,OAAOE,EAAqB,WAEhC,GAAI,EAAEH,GAAS,GAAKA,EAAQE,EAAS,QAAS,MAAM,IAAI,MAAM,8BAAgCF,CAAK,EACnG,GAAI,EAAEA,GAAS,GAAKC,GAAOC,EAAS,QAAS,MAAM,IAAI,MAAM,4BAA8BD,CAAG,EAC9F,GAAI,EAAED,EAAQC,GAAM,MAAM,IAAI,MAAM,4CAA8CD,EAAQ,OAASC,CAAG,EACtG,IAAMG,EAAQF,EAAS,MAAMF,EAAOC,CAAG,EACjCI,EAAOD,EAAM,IAAIE,GAAKA,EAAE,KAAK,EAAE,KAAK,EAAE,EAC5C,OAAO,IAAIH,EAAqBE,EAAMD,CAAK,CAC/C,CAcO,IAAMG,GAAwB,CACjC,UAAW,GACX,yBAA0B,EAC9B,EAOO,SAASC,EAAUC,EAAcC,EAAkC,CACtE,OAAOC,EAAqB,kBAAkBF,EAAMC,GAAWE,EAAY,CAC/E,CAIA,IAAMD,EAAN,MAAME,CAA8C,CAChD,OAAgB,WAA4B,IAAIA,EAAqB,GAAI,CAAC,CAAC,EAC3E,MAAgBC,GAA6C,IAAI,IAAI,CACjE,CAAC,GAAmB,CAAE,MAAO,IAAK,QAAS,KAAM,CAAC,EAClD,CAAC,GAAmB,CAAE,MAAO,IAAK,QAAS,KAAM,CAAC,CACtD,CAAC,EAEQC,GACAC,GAET,YAAYP,EAAcQ,EAAkC,CACxD,KAAKF,GAAQN,EACb,KAAKO,GAAY,OAAO,OAAOC,CAAQ,CAC3C,CAEA,IAAI,OAAgB,CAChB,OAAO,KAAKF,EAChB,CAEA,IAAI,UAA4C,CAC5C,OAAO,KAAKC,EAChB,CAEA,OAAO,kBAAkBP,EAAcC,EAAiC,CACpE,GAAID,IAAS,GACT,OAAOI,EAAqB,WAEhC,IAAMK,EAAYR,EAAQ,UACpBS,EAAmBN,EAAqBC,GAAY,IAAII,CAAS,EACvE,GAAIC,IAAqB,OACrB,MAAM,IAAI,MAAM,0BAA4BD,CAAS,EAGzD,IAAMD,EAAmC,CAAC,EACtCG,EASJ,IARIX,EAAK,WAAW,CAAC,IAAMS,GACvBE,EAAQ,EACRH,EAAS,KAAKE,CAAgB,GAG9BC,EAAQ,EAGLA,EAAQX,EAAK,QAAQ,CACxB,IAAIY,EAAM,GACV,QAASC,EAAIF,EAAOE,EAAIb,EAAK,OAAQa,IACjC,GAAIb,EAAK,WAAWa,CAAC,IAAMJ,EAAW,CAClCG,EAAMC,EACN,KACJ,CAEJ,IAAMC,EAAWF,IAAQ,GAAMZ,EAAK,UAAUW,EAAOC,CAAG,EAAIZ,EAAK,UAAUW,CAAK,EAQhF,GANIG,EAAQ,OAAS,GACjBN,EAAS,KAAKP,EAAQ,yBAClBG,EAAqBW,GAA2BD,CAAO,EACvDE,EAAmB,KAAKF,EAASJ,CAAgB,CACrD,EAEAE,IAAQ,GACR,MAEJJ,EAAS,KAAKE,CAAgB,EAC9BC,EAAQC,EAAM,CAClB,CACA,OAAO,IAAIR,EAAqBJ,EAAMQ,CAAQ,CAClD,CAEA,MAAOO,GAA2BD,EAA8B,CAC5D,IAAMG,EAAcH,EAAQ,QAAQ,GAAG,EACvC,GAAIG,IAAgB,GAAI,CACpB,IAAMC,EAAe,mBAAmBJ,CAAO,EAC/C,OAAOE,EAAmB,KAAKF,EAASI,CAAY,CACxD,KACK,CACD,IAAMA,EAAe,mBAAmBJ,EAAQ,UAAU,EAAGG,CAAW,CAAC,EACnEE,EAAuBL,EAAQ,UAAUG,CAAW,EACpDG,EAAahB,EAAqBiB,GAAqBF,CAAoB,EACjF,OAAOH,EAAmB,KAAKF,EAASI,EAAcE,CAAU,CACpE,CACJ,CAEA,MAAOC,GAAqBC,EAAiD,CACzE,IAAMF,EAAoC,IAAI,IAC1CT,EAAQ,EACZ,KAAOA,EAAQW,EAAQ,QAAQ,CAC3B,IAAIV,EAAM,GACV,QAAS,EAAID,EAAO,EAAIW,EAAQ,OAAQ,IACpC,GAAIA,EAAQ,OAAO,CAAC,IAAM,IAAK,CAC3BV,EAAM,EACN,KACJ,CAEJ,IAAMW,EAAaX,IAAQ,GAAMU,EAAQ,UAAUX,EAAOC,CAAG,EAAIU,EAAQ,UAAUX,CAAK,EAExF,GADAP,EAAqBoB,GAAyBD,EAAWH,CAAU,EAC/DR,IAAQ,GACR,MAEJD,EAAQC,EAAM,CAClB,CACA,GAAIQ,EAAW,KAAO,EAElB,QAAWK,KAAUL,EAAW,OAAO,EACnC,OAAO,OAAOK,CAAM,EAG5B,OAAOL,CACX,CAEA,MAAOI,GAAyBE,EAAeC,EAAqC,CAChF,GAAID,EAAO,CACP,IAAME,EAAUF,EAAM,QAAQ,GAAG,EACjC,GAAIE,IAAY,GAAI,CAChB,IAAMC,EAAO,mBAAmBH,EAAM,UAAU,EAAGE,CAAO,CAAC,EAC3D,GAAIC,EAAK,KAAK,EAAG,CACb,IAAMC,EAAQJ,EAAM,UAAUE,EAAU,CAAC,EACzC,QAAWG,KAAKD,EAAM,MAAM,GAAG,EAAG,CAC9B,IAAML,EAASE,EAAO,IAAIE,CAAI,EAC1BJ,IAAW,OACXA,EAAO,KAAK,mBAAmBM,CAAC,CAAC,EAGjCJ,EAAO,IAAIE,EAAM,CAAC,mBAAmBE,CAAC,CAAC,CAAC,CAEhD,CACJ,CACJ,KACK,CACD,IAAMF,EAAO,mBAAmBH,CAAK,EACrC,GAAIG,EAAK,KAAK,EAAG,CACb,IAAMJ,EAASE,EAAO,IAAIE,CAAI,EAC1BJ,IAAW,OACXA,EAAO,KAAK,EAAE,EAGdE,EAAO,IAAIE,EAAM,CAAC,EAAE,CAAC,CAE7B,CACJ,CACJ,CACJ,CACJ,EAEMb,EAAN,MAAMgB,CAA0C,CAC5C,MAAgBC,GAAwD,IAAI,IAE5E,OAAO,KAAKH,EAAeI,EAAoDd,EAA0D,CACrI,GAAI,OAAOc,GAA4B,SAAU,CAC7C,IAAMhB,EAAegB,EACrB,OAAO,IAAIF,EAAmBF,EAAOZ,EAAcE,CAAU,CACjE,KACK,CACD,IAAMX,EAAYyB,EACZhB,EAAgBY,EAAM,SAASrB,EAAU,OAAO,EAAKqB,EAAM,WAAWrB,EAAU,QAASA,EAAU,KAAK,EAAIqB,EAClH,OAAOE,EAAmB,KAAKF,EAAOZ,EAAcE,CAAU,CAClE,CACJ,CAESe,GACAC,GACAC,GAET,YAAYP,EAAeZ,EAAsBE,EAAqDY,EAAmBC,GAAe,CACpI,KAAKE,GAASL,EACd,KAAKM,GAAgBlB,EACrB,KAAKmB,GAAcjB,CACvB,CAEA,IAAI,OAAgB,CAChB,OAAO,KAAKe,EAChB,CAEA,IAAI,cAAuB,CACvB,OAAO,KAAKC,EAChB,CAEA,IAAI,YAAqD,CACrD,OAAO,KAAKC,EAChB,CAEJ,EC7NO,SAASC,GAAiBC,EAAmBC,EAAsB,CACtE,OAAI,OAAOD,GAAQ,SACRE,GAAmB,MAAMF,EAAKC,CAAW,EAGzCF,GAAiBC,EAAI,KAAMC,CAAW,CAErD,CAEA,IAAMC,GAAN,MAAMC,CAA0C,CAE5C,MAAOC,GAAiBC,EAAqBJ,EAAqC,CAC9E,GAAI,EAAEA,GAAeA,EAAY,KAAK,IAAMA,EAAY,OAAO,CAAC,IAAM,IAClE,OAAOK,EAAU,EAAE,EAGvBH,EAAmBI,GAAqBF,EAAK,MAAOJ,CAAW,EAE/D,IAAMO,EAASP,EAAY,OACvBQ,EAAU,EAEd,QAASC,EAAI,EAAGA,EAAIL,EAAK,SAAS,OAAQK,IAAK,CAC3C,IAAMC,EAAUN,EAAK,SAASK,CAAC,EAE/B,GADAD,GAAWE,EAAQ,MAAM,OACrBH,IAAWC,EACX,OAAOG,GAAQP,EAAM,EAAGK,EAAI,CAAC,CAErC,CAGA,MAAM,IAAI,MAAM,uCAAuCT,CAAW,wBAAwBI,EAAK,KAAK,GAAG,CAC3G,CAEA,MAAOE,GAAqBM,EAAkBZ,EAA2B,CACrE,IAAMO,EAASP,EAAY,OAC3B,GAAIA,EAAY,OAAO,CAAC,IAAM,KAAOA,EAAY,OAAOO,EAAS,CAAC,IAAM,IACpE,MAAM,IAAI,MAAM,0BAA0BP,CAAW,+DAA+D,EAExH,GAAI,CAACY,EAAS,WAAWZ,CAAW,EAChC,MAAM,IAAI,MAAM,0BAA0BA,CAAW,sDAAsDY,CAAQ,GAAG,EAE1H,GAAIA,EAAS,OAASL,GAAUK,EAAS,OAAOL,CAAM,IAAM,IACxD,MAAM,IAAI,MAAM,0BAA0BP,CAAW,uEAAuEY,CAAQ,GAAG,CAE/I,CAEA,MAAOC,GAA8BD,EAAyBZ,EAA2C,CACrG,IAAMc,EAAoBd,EAAY,SAAS,OAC/C,OAAOW,GAAQC,EAAUE,CAAiB,CAC9C,CAEA,OAAO,MAAMC,EAAiBf,EAAsB,CAChD,IAAMY,EAAWP,EAAUU,CAAO,EAC5BC,EAAuBd,EAAmBC,GAAiBS,EAAUZ,CAAW,EAChFiB,EAAwBf,EAAmBW,GAA8BD,EAAUI,CAAoB,EAC7G,OAAO,IAAId,EACPG,EAAUU,CAAO,EACjBC,EACAC,CACJ,CACJ,CAESC,GACAC,GACAC,GAED,YAAYR,EAAyBZ,EAA4BiB,EAAsC,CAC3G,KAAKC,GAAYN,EACjB,KAAKO,GAAenB,EACpB,KAAKoB,GAAyBH,CAClC,CAGA,IAAI,OAAQ,CACR,OAAO,KAAKC,GAAU,KAC1B,CAEA,IAAI,UAAW,CACX,OAAO,KAAKA,GAAU,QAC1B,CAGA,IAAI,aAAc,CACd,OAAO,KAAKC,EAChB,CAEA,IAAI,uBAAwB,CACxB,OAAO,KAAKC,EAChB,CAEA,kBAAkBpB,EAAkC,CAChD,IAAMgB,EAAuBd,EAAmBC,GAAiB,KAAMH,CAAW,EAC5EiB,EAAwBf,EAAmBW,GAA8B,KAAMG,CAAoB,EACzG,OAAO,IAAId,EACP,KACAc,EACAC,CACJ,CACJ,CAEA,UAAmB,CACf,OAAO,KAAKC,GAAU,SAAS,CACnC,CACJ,EAEsBG,EAAf,cAAiDC,CAAyC,CAC7FC,GACAC,GACAL,GAIA,IAAI,aAA2B,CAC3B,OAAI,KAAKK,KAAU,SACf,KAAKA,GAAQ1B,GAAiB,KAAK,IAAI,SAAU,KAAKqB,EAAY,GAE/D,KAAKK,EAChB,CAIA,IAAI,SAA+B,CAC/B,OAAI,KAAKD,KAAa,SAClB,KAAKA,GAAW,KAAK,YAAY,GAE9B,KAAKA,EAChB,CACJ,EFrGO,IAAME,GAAN,cAA0CC,GAAK,eAAgB,CAElE,SAEA,YAGA,IAAI,SAAkB,CAClB,OAAO,KAAK,GAChB,CAEA,IAAI,iBAA2B,CAE3B,OAAO,KAAK,OAAO,YAAiB,EACxC,CACJ,EAEaC,GAAN,cAAoHD,GAAK,cAAwB,CAEpJ,iBAAwB,CACpB,KAAK,QAAa,EACtB,CAEA,mBAA8B,CAC1B,OAAO,MAAM,kBAAqB,CACtC,CACJ,EAEsBE,EAAf,cAAkDC,CAAyC,CAC9FC,GAA6B,CAAC,EAC9BC,GACAC,GAAsE,MACtEC,GAA0C,CAAC,EAE3C,cAAcC,EAAsC,CAChD,OAAI,KAAKF,KAAW,YACV,IAGN,KAAKD,GAAcG,EACZ,GAEf,CAEA,iBAAiBA,EAA8B,CAC3C,OAAO,KAAK,cAAcA,IAAe,OAAY,OAAYC,EAAeD,CAAU,CAAC,CAC/F,CAEA,IAAI,YAAyC,CACzC,OAAO,KAAKH,EAChB,CAEA,UAAUK,EAA8B,CACpC,GAAI,KAAKJ,KAAW,YAChB,MAAM,IAAI,MAAM,qBAAqB,KAAK,UAAUI,CAAM,CAAC,mDAAmD,EAElH,YAAKN,GAAS,KAAKM,CAAM,EAClB,IACX,CAIA,aAAaC,EAAmC,CAC5C,KAAKJ,GAAe,KAAKI,CAAM,CACnC,CAEA,IAAI,UAAoB,CACpB,IAAMC,EAAQ,KAAKN,GACnB,OAAOM,IAAU,OAASA,IAAU,sBACxC,CAEA,MAAM,KAAKC,EAA2F,CAClG,GAAIA,aAAgB,eAChB,MAAM,IAAI,MAAM,uCAAuC,EAE3D,IAAMC,EAAS,MAAMD,EACrB,GAAI,CAGA,OAAO,MAAM,KAAK,SAAS,SAEhB,MAAM,KAAK,aAAa,QAAQ,QAAQC,CAAM,CAAC,CAEzD,EAAE,MAAMC,GAAS,CAEd,MAAMA,CACV,CAAC,CACL,OACOA,EAAO,CAEV,MAAMA,CACV,CACJ,CAIA,MAAM,KAAwB,CAC1B,OAAK,KAAK,SAMC,QAAQ,QAAQ,EAAK,EALrB,KAAK,SAAS,SACV,MAAM,KAAK,aAAa,QAAQ,QAAQ,CAAC,CACnD,CAKT,CAEU,SAASC,EAAwD,CACvE,IAAMJ,EAAQ,KAAKN,GACfW,EAAa,QAAQ,QAAQ,EACjC,GAAIL,IAAU,MACV,KAAKN,GAAS,aACV,KAAKC,GAAe,OAAS,IAC7BU,EAAa,KAAKV,GACb,OACG,CAACW,EAAKC,IAAQD,EAAI,KAAK,IAAMC,EAAI,CAAC,EAClC,QAAQ,QAAQ,CAAC,EACpB,MAAOC,GAAW,CACD,KAAKd,KACL,eACV,KAAKA,GAAS,uBAGtB,CAAC,WAGJM,IAAU,uBACf,KAAKN,GAAS,iBAGd,QAAO,QAAQ,QAAQ,EAAK,EAGhC,OAAAW,EAAaA,EAAW,KAAK,IAAM,CAC/B,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAKX,GAAS,WAClB,CAAC,EAGMW,EAAW,KAAK,SACZD,IAAgB,OAAY,MAAMA,EAAY,EAAI,EAC5D,CACL,CAEU,iBAAwB,CAAC,CACzB,cAAqB,CAAC,CACtB,cAAqB,CAAC,CACpC,EAoYO,IAAMK,EAAN,MAAMC,CAA0D,CAC1DC,GAET,YAAYC,EAA8B,CACtC,KAAKD,GAAYC,CACrB,CAEA,IAAI,UAA+B,CAC/B,OAAO,KAAKD,EAChB,CAEA,cAAcE,EAAqC,CAC/C,OAAO,KAAK,SAAS,cAAcA,CAAU,CACjD,CAEA,iBAAiBA,EAA8B,CAC3C,OAAO,KAAK,SAAS,iBAAiBA,CAAU,CACpD,CAEA,IAAI,YAA6B,CAC7B,OAAO,KAAK,SAAS,UACzB,CAEA,IAAI,SAA4B,CAC5B,OAAO,KAAK,SAAS,OACzB,CAEA,UAAUC,EAA8B,CACpC,YAAK,SAAS,UAAUA,CAAM,EACvB,IACX,CAEA,MAAM,KAAwB,CAC1B,OAAO,MAAM,KAAK,SAAS,IAAI,CACnC,CAEA,MAAM,KAAKC,EAA2F,CAClG,OAAO,MAAM,KAAKJ,GAAU,KAAKI,CAAI,CACzC,CAEA,IAAI,SAA8B,CAC9B,OAAO,KAAKJ,GAAU,OAC1B,CAEA,UAAmB,CACf,MAAO,GAAGD,EAA4B,IAAI,eAAe,KAAK,SAAS,SAAS,CAAC,GACrF,CAEA,OAAc,kBAAqBE,EAAiC,CAChE,GAAIA,aAAoBI,EACpB,OAAOJ,EAAS,kBAAqB,EAEpC,GAAIA,aAAoBF,EACzB,OAAOA,EAA4B,kBAAqBE,EAAS,QAAQ,EAGzE,MAAM,IAAI,MAAM,mCAAmCA,EAAS,YAAY,IAAI,EAAE,CAEtF,CACJ,EA0CO,IAAMK,EAAN,KAAiG,CAC3F,QACA,SACAC,GAAoC,IAAI,IACjDC,GACAC,GAAqB,GAErB,YAAYC,EAAkBC,EAAoBC,EAAwC,CACtF,KAAKL,GAAYM,EAAgB,EAAIH,EAAQ,GAC7C,KAAK,QAAUA,EACf,KAAK,SAAWC,CACpB,CAEA,IAAI,QAAqB,CACrB,OAAO,KAAK,QAAQ,MACxB,CAEA,IAAI,MAAkC,CAClC,OAAO,KAAK,QAAQ,IACxB,CAEA,IAAI,YAAmC,CACnC,OAAO,KAAKJ,EAChB,CAEA,UAAaO,EAA6B,CACtC,OAAO,KAAK,WAAW,IAAIA,CAAI,CACnC,CAEA,WAAyD,CACrD,OAAO,QAAQ,QAAQ,MAAS,CACpC,CAEA,IAAI,WAAoB,CACpB,IAAMC,EAAQ,KAAK,UAAUF,EAAgB,EAC7C,OAAI,KAAKL,KAAWO,IAChB,KAAKP,GAASO,EACd,KAAKN,GAAaM,IAAU,OAAY,IAAIA,CAAK,KAAO,IAErD,KAAKN,EAChB,CACJ,EAEaI,GAAmB,wCGzsBhC,UAAYG,OAAoB,kCAIjB,SAARC,EAA2BC,EAAsB,CACpD,OAAsB,aAAU,kBAAkBA,CAAI,EAAE,CAC5D,CCNO,SAASC,GAAoBC,EAAuC,CACvE,OAAOA,GAAO,IAAI,6BAA6B,IAAM,EACzD,CAEO,IAAMC,GAAkB,4BAExB,SAASC,GAAaF,EAAsC,CAC/D,OAAIA,GAAO,IAAIC,EAAe,EAClBD,EAAM,IAAIC,EAAe,GAAgB,GAE9C,EACX,CCLO,IAAeE,EAAf,KAAwD,CAC3DC,GACU,OAAiBC,EAAU,eAAe,EAE1C,eAAeC,EAAgC,CACrD,KAAKF,GAAsB,CAAC,GAAGE,CAAkB,CACrD,CAEA,UAAUC,EAAgB,CACtB,KAAK,OAASA,CAClB,CAEA,oBAA0C,CACtC,OAAO,KAAKH,EAChB,CAEA,UAAUI,EAAMC,EAA8B,CAC1C,GAAIA,IAAa,OACb,MAAO,GAEX,QAAWC,KAAqB,KAAKN,GACjC,GAAIO,EAAiBF,EAAUC,CAAiB,EAC5C,MAAO,GAGf,MAAO,EACX,CAGJ,EAEaE,EAAN,cAA0BT,CAA0B,CACvD,aAAc,CACV,MAAMU,EAAG,CACb,CAEA,UAAUL,EAAMC,EAA8B,CAC1C,OAAO,MAAM,UAAUD,EAAMC,CAAQ,CACzC,CAEA,MAAM,OAAOK,EAAqCL,EAAqBM,EAAiD,CACpH,IAAMC,EAAO,MAAMF,EACnB,OAAI,KAAK,OAAO,WAAW,OAAO,GAAK,CAACG,GAAoBF,CAAK,GAC7D,KAAKG,GAAUF,CAAI,EAEhBA,CACX,CAEAE,GAAUF,EAAgBD,EAAoC,CAC1D,IAAMI,EAASC,GAAaL,CAAK,EACjC,KAAK,OAAO,MAAM,GAAGI,CAAM,0BAA0B,OAAOH,CAAI,cAAcA,EAAK,YAAiBA,EAAK,MAAWA,EAAK,MAAS,EAAE,CACxI,CACJ,EAGaK,EAAN,MAAMC,UAAsBnB,CAAwB,CAC/C,eAAeoB,EAAuB,CAC1C,MAAM,GAAGA,CAAS,CACtB,CAEA,UAAUf,EAAMC,EAA8B,CAC1C,OAAO,MAAM,UAAUD,EAAMC,CAAQ,GAAKD,IAAS,QACvD,CAEA,MAAM,OAAOM,EAAiCL,EAAqBM,EAAiD,CAEhH,GADAD,EAAQ,MAAMA,EACV,CAACG,GAAoBF,CAAK,GAAK,KAAK,OAAO,WAAW,OAAO,EAAG,CAChE,IAAMS,EAAYJ,GAAaL,CAAK,EAC9BU,EAAe,KAAK,OAAO,WAAW,OAAO,EACnD,KAAK,OAAO,MAAM,GAAGD,CAAS,WAAWC,EAAe,GAAGX,CAAK,GAAK,GAAGA,EAAM,UAAU,EAAG,GAAG,CAAC,KAAK,EAAE,CAC1G,CACA,OAAOA,CACX,CAEA,OAAO,eAA+B,CAClC,OAAO,IAAIQ,EAAcI,GAAe,OAAO,QAAS,OAAO,CAAC,CACpE,CACA,OAAO,cAA8B,CACjC,OAAO,IAAIJ,EAAcI,GAAe,OAAQ,QAAS,OAAO,EAAGb,EAAG,CAC1E,CACJ,ECpFO,IAAec,EAAf,KAAmC,CAC5B,IAAcC,EAAU,YAAY,EAC9CC,GAA+B,GAE/B,IAAI,4BAA4BC,EAAiB,CAC7C,KAAKD,GAA+BC,CACxC,CAEA,IAAI,6BAAuC,CACvC,OAAO,KAAKD,EAChB,CACJ,ECPO,IAAME,EAAN,MAAMC,UAAmCC,CAA2D,CACvG,OAAgB,YAAc,OAAO,OAAO,CAACC,EAAU,mBAAmB,CAAC,EAC3EC,GAEA,YAAYC,EAA6D,CACrE,MAAM,EACN,KAAKD,GAAcC,CACvB,CAEA,IAAI,YAAa,CACb,OAAO,KAAKD,EAChB,CAEA,uBAAkD,CAC9C,OAAOH,EAA2B,WACtC,CAGA,QAAQK,EAAMC,EAAgC,CAC1C,OAAO,KAAKC,GAAmBD,CAAS,GAAMD,EAAK,OAAS,SAAS,IACzE,CAEAE,GAAmBD,EAAgC,CAC/C,GAAIA,IAAc,OAAW,MAAO,GAEpC,QAAWE,KAAsBR,EAA2B,YACxD,GAAIS,EAAiBD,EAAoBF,CAAS,EAC9C,MAAO,GAGf,MAAO,EACX,CAEA,MAAM,YAAYD,EAAMK,EAA2BC,EAAgD,CAC/F,IAAMC,EAAS,KAAKT,GAAY,KAAKE,EAAMK,EAASC,CAAK,EACnDE,EAAS,IAAI,SACnB,aAAkB,CAACC,EAAMC,CAAK,IAAKH,EAC/BC,EAAO,OAAOC,EAAMC,CAAK,EAE7B,OAAOF,CACX,CAGA,KAAKR,EAAMK,EAA2BC,EAAuD,CACzF,MAAM,IAAI,MAAM,qBAAqB,CACzC,CAEJ,EAGaK,EAAN,cAA2Cf,CAA+E,CAC7H,uBAAkD,CAC9C,MAAO,CAACC,EAAU,mBAAmB,CACzC,CAEA,QAAQG,EAAMC,EAAgC,CAC1C,OAAOD,IAAS,UAAYA,EAAK,OAAS,KAAK,OAC3CC,IAAc,QAAaG,EAAiBP,EAAU,oBAAqBI,CAAS,EAE5F,CAEA,YAAYD,EAAMK,EAA2BC,EAAoE,CAC7G,MAAM,IAAI,MAAM,qBAAqB,CACzC,CAEA,KAAKN,EAAMK,EAA2BC,EAA2E,CAC7G,MAAM,IAAI,MAAM,qBAAqB,CACzC,CACJ,ECzDA,IAAMM,EAAN,MAAMC,CAAyD,CAClDC,GACAC,GACTC,GAEA,YAAYC,EAAqB,CAC7BJ,EAAyB,WAAWI,CAAO,EAC3C,KAAKH,GAAWG,EAChB,KAAKF,GAAcG,EAAU,aAAa,GAAGD,EAAQ,mBAAmB,CAAC,EACzE,KAAKD,GAAoB,KAAKD,GAAY,KAAKI,GAAaC,GAAWD,CAAS,CAAC,CACrF,CAEA,IAAI,SAAsB,CACtB,OAAO,KAAKL,EAChB,CAEA,wBAAmD,CAC/C,OAAO,KAAKC,EAChB,CAEA,SAASM,EAAMF,EAAgC,CAC3C,OAAO,KAAKL,GAAS,UAAUO,EAAMF,CAAS,CAClD,CAEA,MAAM,MAAMG,EAAuBD,EAAME,EAAgDJ,EAAuBK,EAA6C,CACzJ,IAAMC,EAAoB,KAAKC,GAAmBH,EAASJ,CAAS,EAC9DQ,EAAO,KAAKb,GAAS,OAAOQ,EAAOG,EAAmBD,CAAK,EACjE,MAAMD,EAAQ,KAAKI,CAAI,CAC3B,CAEA,OAAe,WAAWV,EAAiC,CACnDA,aAAmBW,CAG3B,CAEAF,GAAmBH,EAAgDJ,EAAuB,CACtF,IAAIM,EAAoBI,GAAeN,EAAQ,OAAO,EACtD,GAAIE,EACA,OAAOA,EAEX,IAAIK,EAAW,KAAKd,GACpBS,EAAqBM,GAAYZ,EAAWW,CAAQ,EAAIA,EAAWX,EAC/DM,IACAA,EAAoBO,GAA0BP,EAAmBK,CAAQ,EACzEP,EAAQ,QAAQ,IAAI,eAAgBE,EAAkB,SAAS,CAAC,EAExE,CACJ,EAEA,SAASO,GAA0BC,EAAiBC,EAAoC,CACpF,GAAI,CAACD,EAAK,OAAO,IAAI,SAAS,GAAKC,IAAgB,OAAW,CAC1D,IAAMC,EAAiBD,EAAY,OAAO,IAAI,SAAS,EACvD,GAAIC,EAAgB,CAChB,IAAMC,EAASlB,EAAU,eAAee,EAAK,SAAS,CAAC,EACvD,OAAAG,EAAO,OAAO,IAAI,UAAWD,CAAc,EACpCC,CACX,CACJ,CACA,OAAOH,CACX,CAEA,SAASF,GAAYE,EAAkBH,EAA+B,CAClE,OAAQG,IAAS,QAAa,CAACb,GAAWa,CAAI,GAAKA,EAAK,UAAYf,EAAU,yBAAyB,UAAYY,IAAa,MACpI,CAEA,IAAMO,GAAN,KAAiD,CAC7CC,GACAC,GACAC,GACAC,GAAoB,GACpBC,GAAW,MAAyB,EACpCC,GAAW,MAAyB,EAEpC,aAAc,CACV,KAAK,YAAY,EACjB,KAAK,YAAY,CACrB,CAEA,gBAAgBC,EAAoC,CAChD,KAAKN,GAAmBM,EACxB,KAAK,YAAY,CACrB,CAEA,iBAAiBC,EAA2B,CACpC,KAAKJ,KAAsBI,IAC3B,KAAKJ,GAAoBI,EACzB,KAAK,YAAY,EACjB,KAAK,YAAY,EAEzB,CAEU,aAAoB,CAE1B,GADA,KAAKF,GAAS,OAAS,EACnB,EAAC,KAAKF,GAIV,GAAI,KAAKH,KAAqB,OAC1B,KAAK,SAAS,KAAKK,GAAU,KAAKL,EAAgB,MAEjD,CACD,IAAMQ,EAAa,IAAIC,EACvB,KAAK,SAAS,KAAKJ,GAAUG,CAAU,EACvC,KAAK,SAAS,KAAKH,GAAU,IAAIK,EAA2BF,CAAU,CAAC,CAC3E,CACJ,CAEU,aAAoB,CAC1B,KAAKJ,GAAS,OAAS,EAClB,KAAKD,KAGV,KAAKC,GAAS,KAAK,GAAG,KAAKO,GAAgB,CAAC,EAC5C,KAAK,cAAc,KAAKP,EAAQ,EACpC,CAEU,cAAcQ,EAAyC,CACjE,CAEAD,IAAuC,CACnC,GAAI,CAAC,KAAKR,GACN,MAAO,CAAC,EAEZ,IAAMS,EAAU,MAAyB,EACzC,YAAK,SAASA,EAAS,IAAItC,EAAyB,IAAIuC,CAAa,CAAC,EAC/DD,CACX,CAEA,gBAAgBE,EAAe,CACvB,KAAKb,KAAqBa,IAC1B,KAAKb,GAAmBa,EACxB,KAAK,YAAY,EAEzB,CAEA,4BAA4BC,EAAiB,CACrC,KAAKb,KAAiCa,IACtC,KAAKb,GAA+Ba,EACpC,KAAK,YAAY,EACjB,KAAK,YAAY,EAEzB,CAEA,IAAI,iBAAkB,CAClB,OAAK,KAAKZ,GAGM,MAAyB,EAF9B,CAAC,CAKhB,CAEA,IAAI,cAAe,CACf,OAAO,KAAKC,EAChB,CAEA,IAAI,cAAe,CACf,OAAO,KAAKC,EAChB,CAEA,IAAI,iBAA+C,CAC/C,GAAI,CAAC,KAAKF,GACN,MAAO,CAAC,EAEZ,IAAML,EAAS,MAAyB,EACxC,YAAK,SAASA,EAAQ,IAAIxB,EAAyB0C,EAAc,aAAa,CAAC,CAAC,EACzElB,CACX,CAEU,SAAamB,EAAkBC,EAAU,CAC/C,KAAKC,GAAWD,CAAK,EACrBD,EAAO,KAAKC,CAAK,CACrB,CAEAC,GAAWD,EAAsB,CAI7B,GAHIA,aAAiB5C,IACjB4C,EAAQA,EAAM,SAEdA,IAAU,OACV,OAEJ,IAAME,EAAO,KAAKnB,GAKZc,EAAS,KAAKb,GAChBa,IAAW,SACPG,aAAiBR,IACjBQ,EAAM,4BAA8BH,GAEpCG,aAAiBT,IACjBS,EAAM,4BAA8BH,GAGhD,CACJ,EACeM,GAAf,KAA8D,CACvC,kBAET,YAAYC,EAAkC,CACpD,KAAK,kBAAoBA,CAC7B,CAEA,IAAI,eAA+B,CAC/B,OAAO,KAAK,iBAChB,CAEA,iBAAiBf,EAA2B,CACxC,KAAK,kBAAkB,iBAAiBA,CAAgB,CAC5D,CAEA,IAAI,SAAU,CACV,IAAMT,EAAS,IAAI,MACnB,OAAAA,EAAO,KAAK,GAAG,KAAK,kBAAkB,YAAY,EAClDA,EAAO,KAAK,GAAG,KAAK,kBAAkB,eAAe,EAC9CA,CACX,CAEA,IAAI,SAAwC,CACxC,IAAMA,EAAS,IAAI,MACnB,OAAAA,EAAO,KAAK,GAAG,KAAK,kBAAkB,YAAY,EAClDA,EAAO,KAAK,GAAG,KAAK,kBAAkB,eAAe,EAC9CA,CACX,CAEJ,EAEMyB,GAAN,cAAsCxB,EAAiD,CAEvF,EACMyB,GAAN,cAA2CH,EAAqD,CAC5F,aAAc,CACV,MAAM,IAAIE,EAAyB,CACvC,CACJ,EAEA,SAASE,IAAqD,CAC1D,OAAO,IAAID,EACf,CAEA,IAAOE,GAAQ,CACX,iBAAkB,CACd,OAAQD,EACZ,CACJ,EC5PA,OAAOE,MAAY,kBAGZ,IAAMC,EAAN,MAAMC,UAA8BC,CAAuD,CACrFC,GACAC,GACTC,GACA,QAAU,GAEV,YAAYC,EAAmBC,EAAqB,CAEhD,GADA,MAAM,IAAIC,CAAgB,EACtB,OAAOF,GAAQ,SACf,GAAI,IAAI,SAASA,CAAG,EAChBA,EAAM,IAAI,IAAIA,CAAG,UAEZ,IAAI,SAASA,EAAK,kBAAkB,EACzCA,EAAM,IAAI,IAAIA,EAAK,kBAAkB,MAGrC,OAAM,IAAI,UAAU,sBAAsB,EAGlD,KAAKH,GAAOG,EACZ,KAAK,OAASC,GAAU,MACxB,KAAK,UAAU,OAAQ,KAAKJ,GAAK,QAAQ,EACzC,KAAK,KAAO,KAAKA,GAAK,UAAY,GACtC,CAEA,OAAO,IAAIG,EAAmB,CAC1B,OAAO,IAAIL,EAAsBK,EAAK,KAAK,CAC/C,CAEA,OAAO,KAAKA,EAAmB,CAC3B,OAAO,IAAIL,EAAsBK,EAAK,MAAM,CAChD,CAEA,OAAO,QAAQA,EAAmB,CAC9B,OAAO,IAAIL,EAAsBK,EAAK,SAAS,CACnD,CAEU,aAAmC,CACzC,OAAO,KAAKF,EAChB,CAEA,kBAAyB,CACrB,MAAM,IAAI,MAAM,iEAAiE,CACrF,CAEA,OACA,KAEA,IAAI,MAAO,CACP,OAAO,MAAM,UAAU,KAAKD,GAAK,IAAI,CACzC,CAEA,IAAI,UAAW,CACX,OAAO,MAAM,cAAe,KAAKA,GAAK,SAAU,MAAM,EAAG,EAAE,CAAC,CAChE,CAEA,IAAI,MAAO,CACP,GAAI,KAAKE,KAAU,OAAW,CAC1B,IAAMI,EAAO,KAAKJ,GACZK,GAA4C,iBAAmB,CAEjE,MADc,MAAMD,EAAK,MAAM,CAEnC,GAAG,EACH,OAAOE,EAAO,eAAe,KAAKD,CAAa,CACnD,CACJ,CAEA,MAAsB,CAClB,IAAME,EAAO,KAAKP,GAClB,OAAOO,EAAO,QAAQ,QAAQA,CAAI,EAAI,QAAQ,OAAO,IAAI,MAAM,aAAa,CAAC,CACjF,CAEA,MAAM,MAAO,CAET,OAAO,MADM,MAAM,KAAK,KAAK,GACX,KAAK,CAC3B,CAEA,MAAM,UAAW,CAEb,IAAMC,EAAO,MADA,MAAM,KAAK,KAAK,GACL,KAAK,EAC7B,OAAO,IAAI,gBAAgBA,CAAI,CACnC,CAEA,MAAM,MAAO,CACT,IAAMJ,EAAO,MAAM,KAAK,KAAK,EAC7B,GAAIA,EAAK,OAAS,EACd,OAEJ,IAAMI,EAAO,MAAMJ,EAAK,KAAK,EAC7B,OAAO,KAAK,MAAMI,CAAI,CAC1B,CAEA,MAAM,UAAUD,EAAmE,CAC/E,GAAIA,IAAS,OAAW,CACpB,KAAKP,GAAQ,IAAI,KAAK,CAAC,CAAC,EACxB,MACJ,CACA,GAAIO,aAAgB,eAAgB,CAChC,IAAME,EAAsB,CAAC,EACvBC,EAASH,EAAK,UAAU,EAC1BI,EAAO,GACX,KAAO,CAACA,GAAM,CACV,GAAM,CAAE,MAAAC,EAAO,KAAMC,CAAS,EAAI,MAAMH,EAAO,KAAK,EAChDG,EACAF,EAAO,GAGPF,EAAO,KAAKG,CAAK,CAEzB,CACA,KAAKZ,GAAQ,IAAI,KAAKS,CAAM,CAChC,MAEIF,EAAO,MAAMA,EACT,OAAOA,GAAS,SAChB,KAAKP,GAAQ,IAAI,KAAK,CAACO,CAAI,EAAG,CAAE,KAAM,YAAa,CAAC,EAGpD,KAAKP,GAAQ,IAAI,KAAK,CAACO,CAAI,CAAC,EAG/B,KAAK,QAAQ,IAAI,cAAc,GAChC,KAAK,UAAU,eAAgB,KAAKP,GAAM,MAAQ,0BAA0B,CAGpF,CAEA,IAAI,KAAM,CACN,OAAO,IAAI,IAAI,KAAK,KAAO,KAAKF,GAAK,OAAS,KAAKA,GAAK,KAAM,GAAG,KAAK,QAAQ,MAAM,KAAK,IAAI,EAAE,CACnG,CAEA,UAAUgB,EAAcF,EAA2C,CAC/D,OAAC,KAAK,QAA+B,IAAIE,EAAMF,CAAK,EAC7C,IACX,CAEA,UAAUE,EAAcF,EAAkC,CACtD,OAAC,KAAK,QAA+B,IAAIE,EAAMF,CAAK,EAC7C,IACX,CACJ,EAEaG,EAAN,cAAqCC,CAAuE,CAC/GC,GACAjB,GAAyC,IAAM,CAC3C,MAAM,IAAI,MAAM,kFAAkF,CACtG,EAEA,aAAc,CACV,MAAM,IAAIG,CAAgB,EAC1B,KAAKc,GAAgB,MAAOV,GAAS,CACjC,IAAME,EAAsB,CAAC,EACzBS,EACJ,KAAKlB,GAAQ,KACTkB,IAAeZ,EAAO,eAAe,KAAKG,CAAM,EACzCS,GAGX,IAAMR,EAASH,EAAK,UAAU,EAC1BI,EAAO,GACX,EAAG,CACC,GAAM,CAAE,MAAAC,EAAO,KAAMC,CAAS,EAAI,MAAMH,EAAO,KAAK,EAChDG,EACAF,EAAO,GAGPF,EAAO,KAAKG,CAAK,CAEzB,OACO,CAACD,GACR,MAAO,EACX,CACJ,CAEA,IAAI,YAAa,CACb,OAAO,MAAM,UACjB,CAEA,IAAI,aAAaQ,EAAgE,CAC7E,KAAKnB,GAAQ,IAAM,CACf,MAAM,IAAI,MAAM,yCAAyC,CAC7D,EACA,KAAKiB,GAAgBE,CACzB,CAGA,mBAA0B,CACtB,MAAM,IAAI,MAAM,wDAAwD,CAC5E,CAEU,iBAAwB,CAClC,CAEU,cAAqB,CAC/B,CAEU,cAAqB,CAC3B,QAAWC,KAAU,KAAK,QACtB,KAAK,QAAQ,IAAI,aAAc,MAAM,eAAeA,CAAM,CAAC,CAEnE,CAEA,aAAab,EAAmD,CAC5D,IAAMc,GAAM,iBAAmB,CAC3B,IAAMC,EAAW,MAAMf,EACnBe,IAAa,SAGjB,MAAMA,EACV,GAAG,EACH,OAAO,KAAKL,GAAcX,EAAO,eAAe,KAAKe,CAAE,CAA8B,CACzF,CAEA,MAAM,KAAwB,CAC1B,OAAO,KAAK,SAAS,SACV,MAAM,KAAKJ,GAAcX,EAAO,eAAe,KAAK,CAAC,CAAC,CAAmB,CACnF,CACL,CAEA,SAAU,CACN,OAAO,KAAKN,GAAM,CACtB,CACJ,EC1OO,IAAMuB,EAAN,cAAwCC,CAA4B,CAE3E,ECKA,OAAOC,OAAY,kBAInB,IAAMC,GAAN,cAAiD,KAAM,CAC1C,kBAET,YAAYC,EAA8BC,EAA6B,CAAC,EAAG,CACvE,MAAM,gDAAgDD,CAAQ,GAAIC,CAAO,EACzE,KAAK,kBAAoBD,CAC7B,CACJ,EAQA,eAAeE,IAA4B,CACvC,GAAI,CACA,OAAO,MAAM,IAAI,QAAiB,CAACC,EAAQC,IAAW,CAElD,IAAMC,EAAU,IAAI,QAAW,CAACC,EAASC,IAAW,CAChD,QAAQ,QAAQ,EAAE,KAAK,IAAM,CACzBJ,EAAO,CAAC,QAAAE,EAAS,QAAAC,EAAS,OAAAC,CAAM,CAAC,CACrC,CAAC,CACL,CAAC,CACL,CAAC,CACL,OACOC,EAAO,CACV,MAAMA,CACV,CACJ,CAEO,IAAMC,EAAN,MAAMC,CAAoD,CAC7D,MAAgBC,GAAUC,EAAU,6BAA6B,EACxDC,GACAC,GAET,YAAYC,EAA0BC,EAAmB,CACrD,KAAKH,GAAeE,EACpB,KAAKD,GAAWE,CACpB,CAEA,MAAM,QAAQC,EAAoBC,EACpBC,EAA6F,CAEvG,IAAMC,EAAmB,MAAMlB,GAAW,EACpCmB,EAAc,MAAMnB,GAAW,EAC/BoB,EAAkD,CAAC,MAAS,EAE5DC,EAAoB,IAAIC,EAAsBN,EAAKD,CAAM,EACzDQ,EAAqB,IAAIC,EAE/B,OAAAH,EAAkB,aAAe,MAAOI,GAAiB,CACrD,KAAK,IAAI,4BAA6BV,EAAQC,CAAG,EACjD,IAAMU,EAAoB,MAAM,KAAK,aAAaL,EAAmBI,CAAY,EAC3EE,EAAgB,KAAK,gBAAgBJ,EAAoBG,CAAiB,EAEhF,GAAI,CACA,MAAM,KAAKf,GAAae,EAAmBC,CAAa,EACxDR,EAAY,QAAQ,CACxB,OAASS,EAAG,CACRT,EAAY,OAAOS,CAAC,CACxB,CACA,MAAO,EAEX,EAEAL,EAAmB,aAAe,MAAOE,IACrC,KAAK,IAAI,gCAAiCV,EAAQC,CAAG,EACrDI,EAAc,CAAC,EAAI,KAAK,cAAcG,EAAoBE,CAAY,EAC/D,IAEX,KAAK,IAAI,8BAA+BV,EAAQC,CAAG,EAEnDC,EAAgBI,CAAiB,EAC5B,KAAK,IAAM,CACRH,EAAiB,QAAQ,CAC7B,CAAC,EACA,MAAMZ,GAAS,CACZY,EAAiB,OAAOZ,CAAK,CACjC,CAAC,EAEE,QAAQ,IAAI,CAACY,EAAiB,QAASC,EAAY,OAAO,CAAC,EAC7D,MAAOb,GAAU,CACd,IAAMR,EAAWsB,EAAc,CAAC,EAChC,MAAMtB,IAAa,OAAY,IAAID,GAAmCC,EAAU,CAAC,MAAOQ,CAAK,CAAC,EAAIA,CACtG,CAAC,EAAE,KAAK,IACac,EAAc,CAAC,GACb,KAAK,cAAcG,EAAoB3B,GAAO,eAAe,KAAK,CAAC,CAAC,CAA8B,CACxH,CAET,CAEQ,IAAIiC,EAAiBd,EAAoBC,EAAgB,CACzDR,EAAqBC,GAAQ,WAAW,OAAO,GAC/CD,EAAqBC,GAAQ,MAAM,GAAGoB,CAAO,IAAId,CAAM,KAAKC,EAAI,IAAI,GAAG,CAE/E,CAEA,MAAc,aAAac,EAAgCC,EAA6D,CACpH,IAAMhB,EAASe,EAAQ,OACjBd,EAAMc,EAAQ,IACdE,EAAUF,EAAQ,QAClBG,EAAWH,EAAQ,QACnB7B,EAAS,IAAIiC,EAAsBlB,EAAKD,CAAM,EACpD,QAAWoB,KAAQH,EAAQ,KAAK,EAAG,CAC/B,IAAII,EAAQJ,EAAQ,IAAIG,CAAI,EAC5B,GAAIC,IAAU,OAIV,GAHI,OAAOA,GAAU,WACjBA,EAAQ,OAAOA,CAAK,GAEpB,OAAOA,GAAU,SACjBnC,EAAO,UAAUkC,EAAMC,CAAK,MAE5B,SAAWC,KAAKD,EACZnC,EAAO,UAAUkC,EAAME,CAAC,CAIxC,CACA,aAAMpC,EAAO,UAAU8B,CAAI,EACpB9B,CACX,CAEQ,gBAAgBH,EAA8BgC,EAAgD,CAClG,OAAOA,EAAQ,SAAW,OAAS,IAAIQ,EAA0BxC,CAAQ,EAAIA,CAEjF,CAEQ,cAAcA,EAAkCiC,EAAqD,CACzG,IAAMQ,EAASzC,EAAS,WAClBkC,EAAUlC,EAAS,QACnBmC,EAAWnC,EAAS,QACpBG,EAAS,IAAIuC,EAAuBD,CAAM,EAChD,QAAWJ,KAAQH,EAAQ,KAAK,EAAG,CAC/B,IAAII,EAAQJ,EAAQ,IAAIG,CAAI,EAC5B,GAAIC,IAAU,OAIV,GAHI,OAAOA,GAAU,WACjBA,EAAQ,OAAOA,CAAK,GAEpB,OAAOA,GAAU,SACjBnC,EAAO,UAAUkC,EAAMC,CAAK,MAE5B,SAAWC,KAAKD,EACZnC,EAAO,UAAUkC,EAAME,CAAC,CAIxC,CACA,OAAApC,EAAO,KAAO8B,EACP9B,CACX,CACJ,ECpKA,OAAS,aAAAwC,OAAiB,qBAI1B,IAAMC,GAAMC,EAAU,0BAA0B,EA+DzC,SAASC,GAAsBC,EAAmE,CACrG,GAAIA,EAAe,CACf,IAAMC,GAASD,EAAc,OAASA,EAAc,WAAa,CAAC,GAAG,IAAIE,GAAU,UAAU,QAAQ,EAC/FC,GAASH,EAAc,OAASA,EAAc,WAAa,CAAC,GAAG,IAAIE,GAAU,UAAU,QAAQ,EACrG,MAAO,CACH,YAAaF,EAAc,aAAe,QAC1C,QAASA,EAAc,SAAW,QAClC,MAAAG,EACA,MAAAF,CACJ,CACJ,CACJ,CCvBO,IAAMG,GAAwC,MAAOC,GACjDC,GAAM,EAEjBF,GAAY,SAAW,IAAM,eAE7B,IAAMG,GAAe,OAAO,OAAO,CAAC,CAAC,EACxBC,EAAwB,OAAO,OAAO,CAAC,MAAO,GAAO,UAAWD,EAAY,CAAC,EAC7ED,GAAQ,CAACG,EAAoCF,MAC/C,CAAE,MAAO,GAAM,UAAAE,CAAU,GAGvBC,GAA8F,CAACA,EAASC,IAAS,CAC1H,IAAMC,EAASD,GAAM,OACfE,EAAU,MAAOC,GAAsD,CACzE,IAAMC,EAAUD,EAAS,QACnBE,EAAOD,EAAQ,KACrB,GAAIH,IAAW,QAAaG,EAAQ,SAAWH,EAC3C,OAAOJ,EAEX,GAAI,OAAOE,GAAY,SACnB,OAAIM,IAASN,EACFJ,GAAM,EAEVE,EAEN,CACD,IAAMF,EAAQI,EAAQ,KAAKM,CAAI,EAC/B,OAAIV,IAAU,KACHE,EAEJ,CAAC,MAAO,GAAM,UAAW,CAAC,GAAGF,EAAM,MAAM,CAAC,CACrD,CACJ,EACA,OAAAO,EAAQ,SAAW,IACR,WAAWH,EAAQ,SAAS,CAAC,YAAYE,GAAU,OAAO,IAE9DC,CAEX,EAsCO,IAAMI,GAA2C,MAAO,CAAC,QAAAC,CAAO,IACnDA,EAAQ,SAAWA,EAAQ,QAAQ,IAAI,SAAS,GAAG,YAAY,IAAM,YACpEC,GAAM,EAAIC,EAE/BH,GAAe,SAAW,IAAM,oBCxHhC,OAAS,aAAAI,OAAiB,qBAmB1B,eAAsBC,GAAUC,EAAuBC,EAAsBC,EAAoC,CAC7G,IAAMC,EAAY,CAACC,EAAiDC,IAAoC,CAMpG,GAAIA,GAAS,KAAM,CACf,IAAMC,EAAmBD,EAAQ,OAAS,GAAO,CAC7C,aAAcA,EAAQ,SAAS,OAAO,IAAIP,GAAU,UAAU,QAAQ,EACtE,aAAcM,EAAQ,SAAW,OAAY,CAAC,GAAG,EAAI,CAACA,EAAQ,MAAM,EACpE,iBAAkBC,EAAQ,WAAW,SAAW,YAAc,GAAO,MACzE,EAAIA,EAAQ,KACNE,EAAOH,EAAQ,KACrBF,EAAO,KAAK,KAAK,CAACK,EAAMD,CAAI,CAAC,CACjC,CACJ,EAEME,EAAa,IAAI,KAAkC,CAErD,UAAUC,EAA8C,CACpDA,EAAS,QAAQ,CAAC,CAAC,QAAAL,EAAS,QAAAC,EAAS,QAAAK,CAAO,IAAM,CAC9C,IAAMC,EAAUC,GAAQd,GAAU,UAAU,SAASM,EAAQ,IAAI,EAAsB,CAAC,OAAQA,EAAQ,MAAM,CAAC,EAC3GC,GAAS,WACTH,EAAO,UAAU,KAAK,CAACS,EAASN,EAAQ,SAAS,CAAC,EAGtDF,EAAUC,EAASC,CAAO,EAC1B,IAAMQ,EAAa,MAAOC,EAA6BC,IAA6C,CAChG,GAAM,CAAC,MAAAC,EAAO,UAAAC,EAAS,EAAI,MAAMN,EAAQG,CAAQ,EAC7CE,EACA,MAAMN,EAAQI,EAAUG,EAAS,EAEjC,MAAMF,EAAK,CAEnB,EACAb,EAAO,WAAW,KAAKW,CAAU,CACrC,CAAC,CACL,CAEA,UAAUK,EAA4C,CAClD,OAAW,CAAC,KAAAX,EAAM,QAAAY,EAAS,QAAAd,CAAO,IAAKa,EAAS,CAC5C,IAAME,EAAQb,GAAQ,IAGtBL,EAAO,QAAQ,IAAIkB,EAAO,CACtB,QAASb,IAAS,QAAaA,IAAS,IACxC,KAAMF,GAAS,KACf,QAASc,EACT,eAAgBd,GAAS,eACzB,UAAWA,GAAS,UACpB,cAAegB,GAAsBhB,GAAS,OAAO,CACzD,CAAC,CACL,CACJ,CACJ,EACA,MAAML,EAAIQ,EAAYP,CAAM,CAChC,CCnFO,SAASqB,MAAcC,EAAgE,CAC1F,GAAI,CAAC,MAAM,QAAQA,CAAU,EACzB,MAAM,IAAI,MAAM,2BAA2B,EAE/C,IAAMC,EAAMD,EAAW,KAAK,EAC5B,QAAWE,KAAMD,EACb,GAAI,OAAOC,GAAO,WACd,MAAM,IAAI,MAAM,0CAA0C,EAGlE,OAAO,eAAgBC,EAAQC,EAAmC,CAC9D,IAAMC,EAAW,MAAOC,EAAWC,IAAoC,CACnE,IAAML,EAAKI,IAAML,EAAI,OAASG,EAAOH,EAAIK,CAAC,EAC1C,GAAIJ,IAAO,OACP,OAEJ,IAAIM,EAAa,GACbC,EAAe,GAabC,EAAS,MAAMR,EAAGK,EAZT,MAAOI,GAAgB,CAClC,GAAIH,EACA,MAAM,IAAI,MAAM,8BAA8B,EAElDA,EAAa,GACb,GAAI,CACA,OAAO,MAAMH,EAASC,EAAI,EAAGK,GAAWJ,CAAa,CACzD,QACA,CACIE,EAAe,EACnB,CACJ,CAC6C,EAC7C,GAAID,GAAc,CAACC,EACf,MAAM,IAAI,MAAM;AAAA,qFAA+H,EAEnJ,OAAOC,CACX,EAEA,OAAOL,EAAS,EAAGF,CAAG,CAC1B,CACJ,CCjCA,OAAS,qBAAAS,OAAyB,mBCblC,OAAS,qBAAAC,OAAyB,mBCC3B,SAASC,GAA0BC,EAAuB,CAC7D,GAAIA,GAAU,KACV,MAAO,GAEX,GAAM,CAAE,KAAAC,EAAM,QAAAC,CAAQ,EAAIF,EAC1B,OAAOC,IAAS,cACZA,IAAS,SACTA,IAAS,8BACTC,GAAS,YAAY,EAAE,SAAS,gBAAgB,GAChDA,GAAS,YAAY,EAAE,SAAS,gBAAgB,GAChDA,GAAS,YAAY,EAAE,SAAS,SAAS,CACjD,CAEO,SAASC,GAAmCH,EAAcI,EAAyB,CAEtF,OAD6BL,GAA0BC,CAAK,GAEpDI,EAAO,WAAW,OAAO,EACzBA,EAAO,MAAM,uCAAwCJ,CAAK,EAErDI,EAAO,WAAW,OAAO,GAC9BA,EAAO,MAAM,wCAAwCJ,EAAM,OAAO,qDAAqD,EAEpH,IAEJ,EACX,CCvBO,IAAMK,GAAN,KAAgD,CAC1CC,GAET,YAAYC,EAAsB,CAC9B,GAAIA,GAAa,KAAgC,MAAM,IAAI,MAAM,wCAAwC,EACzG,KAAKD,GAAYC,CACrB,CAEA,IAAI,UAAuB,CACvB,OAAO,KAAKD,EAChB,CAEA,MAAM,OAAOE,EAA4C,CACrD,OAAO,MAAM,KAAKF,GAAU,OAAOE,CAAQ,CAC/C,CAEA,UAAmB,CACf,MAAO,gCAAgC,KAAKF,EAAS,GACzD,CACJ,EAEaG,GAAN,cAAsCJ,EAAoB,CACpDK,GACT,YAAYH,KAAyBI,EAAuC,CACxE,MAAMJ,CAAQ,EACd,KAAKG,GAAiB,CAAC,GAAKC,CAAc,EAC1C,OAAO,OAAO,KAAKD,EAAc,CACrC,CAEA,IAAI,eAAgD,CAChD,OAAO,KAAKA,EAChB,CAEA,OAAOF,EAA4C,CAC/C,IAAII,EACJ,GAAI,CACAA,EAAa,MAAM,OAAOJ,CAAQ,CACtC,OACOK,EAAG,CACND,EAAa,QAAQ,OAAOC,CAAC,CACjC,CAIA,QAAWC,KAAW,KAAKJ,GACvBE,EAAaA,EAAW,MAAM,MAAOG,GAAW,CAC5C,IAAMC,EAAQD,aAAkB,MAAQA,EAAS,IAAI,MAAM,OAAOA,CAAM,CAAC,EACzE,MAAMD,EAAQ,OAAON,EAAUQ,CAAK,CACxC,CAAC,EAEL,OAAOJ,CACX,CACJ,EAEaK,GAAN,MAAMC,CAAgD,CAChDC,GACAC,GAEKC,GACAC,GAEd,OAAO,GAAGR,KAAwBS,EAAsB,CACpD,IAAMC,EAAa,CAAC,GAAGD,CAAO,EACxBE,EAAS,IAAIP,EAAsBK,EAAST,CAAO,EACnDY,EAAQR,EAAsB,UAAUK,EAAST,CAAO,EAC9D,OAAAW,EAAOJ,GAAWK,EAAML,GACxBI,EAAOH,GAASI,EAAMJ,GACfG,CACX,CAEA,OAAe,UAAUF,EAAsBT,EAA4C,CACvF,IAAIY,EAAQ,IAAIR,EAAsBK,EAAST,EAAS,OAAW,MAAS,EAC5E,QAAWa,IAAW,CAAC,GAAGJ,CAAO,EAAE,QAAQ,EACvCG,EAAQ,IAAIR,EAAsBK,EAAST,EAASa,EAASD,CAAK,EAEtE,OAAOA,CACX,CAEQ,YAAYH,EAAsBT,EAAqBa,EAAsBD,EAA+B,CAChH,KAAKP,GAAWI,EAChB,KAAKH,GAAWN,EAChB,KAAKO,GAAWM,EAChB,KAAKL,GAASI,CAClB,CAEA,IAAI,SAAoC,CACpC,OAAO,KAAKP,EAChB,CAEA,IAAI,SAAsB,CACtB,OAAO,KAAKC,EAChB,CAEA,MAAM,OAAOZ,EAA4C,CACjD,KAAKa,KAAa,QAAa,KAAKC,KAAW,OAC/C,MAAM,KAAKM,GAAc,KAAKP,GAAU,KAAKC,GAAQd,CAAQ,EAG7D,MAAM,KAAKY,GAAS,OAAOZ,CAAQ,CAE3C,CAEAoB,GAAcC,EAAmBH,EAA8BlB,EAA4C,CACvG,OAAOqB,EAAO,OAAOrB,EAAUkB,CAAK,CACxC,CACJ,EAEaI,GAAN,cAAkCzB,EAAoB,CAChD0B,GAET,YAAYjB,KAAwBS,EAA2B,CAC3D,MAAMT,CAAO,EACb,KAAKiB,GAASd,GAAsB,GAAGH,EAAS,GAAIS,CAAQ,CAChE,CAEA,IAAI,SAAU,CACV,OAAO,KAAKQ,GAAO,OACvB,CAEA,OAAOvB,EAA4C,CAC/C,OAAO,KAAKuB,GAAO,OAAOvB,CAAQ,CACtC,CACJ,EF/GA,IAAMwB,GAAN,KAA4B,CAEfC,GAETC,GAA0C,OAC1CC,GAAwC,GAC/BC,GACTC,GAEA,YAAYC,EAAgBC,EAAsB,CAC9C,KAAKN,GAAUK,EACf,KAAKF,GAAYG,CACrB,CAEA,IAAI,iBAAyC,CACzC,OAAI,KAAKL,KAAqB,SAC1B,KAAK,gBAAkBM,GAAY,iBAAiB,OAAO,GAExD,KAAKN,EAChB,CAEA,IAAI,gBAAgBO,EAAmC,CACnD,GAAIA,GAAe,KACf,MAAM,IAAI,MAAM,+CAA+C,EAEnE,KAAKP,GAAmBO,EAExB,KAAKN,GAA+B,GACpC,QAAWO,KAAU,KAAKR,GAAiB,QACvC,GAAIQ,aAAkBC,GAAuBD,EAAO,4BAA6B,CAC7E,KAAKP,GAA+B,GACpC,KACJ,CAER,CAEU,eAAeS,EAA4BC,EAAiD,CAElG,OADiB,IAAIC,EAAmBF,EAASC,EAAU,KAAK,eAAe,CAEnF,CAEA,IAAI,QAAQE,EAA6D,CACrE,KAAKV,GAAWU,CACpB,CAGA,cAAcC,EAA8B,CACxC,IAAIC,EAAS,IAEb,QAAWC,KAAOF,EAAQ,KAAK,EAC3B,GAAK,KAAKb,GAIL,CACD,IAAMgB,EAAQH,EAAQ,IAAIE,CAAG,EAC7BD,GAAU,IAAIC,CAAG,OAAOC,CAAK,KACjC,KAPwC,CACpCF,GAAU,WACV,KACJ,CAMJ,OAAIA,EAAO,SAAS,IAAI,IACpBA,EAASA,EAAO,MAAM,EAAG,EAAE,GAE/BA,GAAU,IACHA,CAEX,CAEA,cAAcL,EAAoC,CAC9C,IAAMQ,EAAQR,EAAQ,IAAI,OAC1B,MAAO,QAAQA,EAAQ,MAAM,KAAKA,EAAQ,IAAI,GAAGQ,CAAK,EAC1D,CAEA,WAAWC,EAA6B,CACpC,GAAI,KAAKpB,GAAQ,WAAW,OAAO,EAAG,CAClC,IAAMqB,EAAQ,KAAKrB,GAAQ,WAAW,OAAO,EAC7C,KAAKA,GAAQ,MAAM,GAAGoB,EAAS,SAAS,GAAG,KAAK,cAAcA,EAAS,OAAO,CAAC,GAAGC,EAAQ,cAAc,KAAK,cAAcD,EAAS,QAAQ,OAAO,CAAC,GAAK,EAAE,GAAG,CAElK,CACJ,CAEA,YAAYA,EAA6B,CACrC,GAAI,KAAKpB,GAAQ,WAAW,OAAO,EAAG,CAClC,IAAMqB,EAAQ,KAAKrB,GAAQ,WAAW,OAAO,EACvCsB,EAASF,EAAS,SAAS,WACjC,KAAKpB,GAAQ,MAAM,GAAGoB,EAAS,SAAS,aAAaE,GAAU,QAAQ,GAAGD,EAAQ,cAAc,KAAK,cAAcD,EAAS,SAAS,OAAO,CAAC,GAAK,EAAE,GAAG,CAC3J,CACJ,CAEA,sBAAsBA,EAA6BG,EAAc,CAC7D,GAAM,CAAE,QAAAZ,EAAS,SAAAC,EAAU,UAAAY,CAAU,EAAIJ,EAEzC,GAAIR,EAAS,cAAca,EAAW,qBAAqB,EAAG,CAC1D,KAAKzB,GAAQ,MAAM,GAAGwB,CAAS,wBAAwB,KAAK,cAAcb,CAAO,CAAC,GAAIY,CAAK,EAC3F,MACJ,KACK,IAAIG,GAAmCH,EAAO,KAAKvB,EAAO,EAE3D,OAIA,WAAKA,GAAQ,MAAM,GAAGwB,CAAS,UAAUD,EAAM,OAAO,QAAQ,KAAK,cAAcZ,CAAO,CAAC,wBAAwBC,EAAS,UAAU,IAAKW,CAAK,EACxIA,EAGd,CAEA,MAAM,IAAIH,EAA4C,CAClD,OAAO,MAAM,KAAKjB,GAAU,OAAOiB,CAAQ,CAC/C,CAEA,MAAM,KAAKT,EAA4BC,EAA6C,CAEhF,IAAMQ,EAAW,KAAK,eAAeT,EAASC,CAAQ,EAChDe,EAAW,KACb,KAAK,WAAWP,CAAQ,EACjB,KAAK,IAAIA,CAAQ,EACnB,KAAK,IAAM,CACR,KAAK,YAAYA,CAAQ,CAC7B,CAAC,EACA,MAAOG,GAAiB,CACrB,KAAK,sBAAsBH,EAAUG,CAAK,CAC9C,CAAC,EACA,KAAK,SAAY,CACd,MAAMH,EAAS,SAAS,IAAI,CAChC,CAAC,GAGT,MAAM,IAAI,QAAc,CAACQ,EAASC,IAAW,CACrC,KAAKzB,KAAa,OAClB,KAAKA,GAAS,IAAI,CAAE,SAAAgB,CAAS,EAAG,IAAM,CAClCO,EAAS,EAAE,KAAK,IAAMC,EAAQ,CAAC,EAAE,MAAOL,GAAUM,EAAON,CAAK,CAAC,CACnE,CAAC,EAGDI,EAAS,EAAE,KAAK,IAAMC,EAAQ,CAAC,EAAE,MAAOL,GAAUM,EAAON,CAAK,CAAC,CAEvE,CAAC,CACL,CACJ,EAEaO,GAAN,MAAMC,CAAsB,CACtBC,GACAC,GAAwB,CAAC,EACzBC,GAAwC,CAAC,EACzCC,GAA0B,CAAC,EACpCC,GACAhC,GAAgE,IAAIiC,GACpEpC,GAEA,YAAYqC,EAAwB,CAChC,KAAKN,GAAcM,CACvB,CAEA,OAAO,WAAWA,EAA+C,CAC7D,OAAO,IAAIP,EAAsBO,CAAU,CAC/C,CAEA,UAAUC,EAA4B,CAClC,OAAIA,GACA,KAAKN,GAAS,KAAK,GAAGM,CAAO,EAE1B,IACX,CAEA,WAAWC,EAAkD,CACzD,OAAAA,EAAS,KAAKL,EAAW,EAClB,IACX,CAEA,oBAAoBM,EAAmC,CACnD,OAAIA,GACA,KAAKP,GAAmB,KAAK,GAAGO,CAAQ,EAErC,IACX,CAEA,kBAAkBD,EAAuD,CACrE,OAAAA,EAAS,KAAKN,EAAkB,EACzB,IACX,CAEA,QAAQpB,EAAmE,CACvE,YAAKV,GAAWU,EACT,IACX,CAEA,gBAAgBN,EAAyC,CACrD,YAAKP,GAAmBO,EACjB,IACX,CAEA,oBAA8B,CAC1B,OAAO,KAAKP,KAAqB,MACrC,CAEA,qBAAqByC,EAAwD,CACzE,GAAI,KAAKN,KAAsB,OAC3B,KAAKA,GAAoBM,MAExB,CACD,IAAMC,EAAoB,KAAKP,GAC/B,KAAKA,GAAqBQ,IACtBA,EAAUF,EAAUE,CAAO,EAC3BA,EAAUD,EAAkBC,CAAO,EAC5BA,EAEf,CACA,OAAO,IACX,CAEA,yBAAmC,CAC/B,OAAO,KAAKR,KAAsB,MACtC,CAEA,OAAqB,CACjB,IAAM/B,EAASwC,EAAU,MAAM,EAC3BC,EAAwB,IAAIC,GAAoB,KAAKf,GAAa,GAAG,KAAKC,EAAQ,EACtFa,EAAY,IAAIE,GAAwBF,EAAW,GAAG,KAAKZ,EAAkB,EAE7E,IAAMe,EAAU,IAAIlD,GAAsBM,EAAQyC,CAAS,EACvD,KAAK1C,KAAa,SAAW6C,EAAQ,QAAU,KAAK7C,IACpD,KAAKH,KAAqB,SAC1BgD,EAAQ,gBAAkB,KAAKhD,IAEnC,IAAMiD,EAAuB,MAAOvC,EAASC,IAAaqC,EAAQ,KAAKtC,EAASC,CAAQ,EAGxF,OAAO,KAAKwB,GAAoB,KAAKA,GAAkBc,CAAO,EAAIA,CACtE,CACJ,EDlOO,SAASC,GAAUC,EAAuC,CAC7D,OAAO,IAAIC,GAAQD,CAAG,CAC1B,CAEO,SAASE,IAAkC,CAC9C,OAAO,IAAIC,EACf,CAEA,IAAMC,GAAN,KAA8C,CACjCC,GACAC,GACT,YAAYC,EACAC,EACAC,EAA6B,CACrC,KAAKJ,GAAaE,EAClB,KAAKD,GAAWE,CACpB,CAEA,MAAQ,MAAOE,EAAqBC,IAA0C,CAC1E,GAAI,CACA,IAAMC,EAASD,GAAM,QAAwB,MACvCE,EAAM,IAAI,IAAIH,EAAO,KAAKJ,EAAQ,EAClCQ,EAAW,MAAM,KAAKT,GAAW,QAAQO,EAAQC,EAAK,MAAOE,GAAY,CAE3E,IAAMC,EAAU,IAAI,QAAQL,GAAM,OAAO,EACzC,OAAW,CAACM,EAAMC,CAAK,IAAKF,EAAQ,QAAQ,EACxCD,EAAQ,QAAQ,IAAIE,EAAMC,CAAK,EAEnC,IAAIC,EAAOR,GAAM,MAAQ,QAAQ,QAAQ,EACzC,GAAIQ,aAAgB,eAChB,MAAM,IAAI,MAAM,yBAAyB,OAAOR,GAAM,IAAI,mBAAmB,EAEjF,GAAIQ,aAAgB,SAAU,CAE1B,IAAMC,EAAkB,MAAM,KAAKD,EAAK,QAAQ,CAAC,EACjDA,EAAO,IAAI,gBACX,OAAW,CAACE,EAAKH,EAAK,IAAKE,EACvBD,EAAK,OAAOE,EAAKH,GAAM,SAAS,CAAC,CAEzC,CACIC,aAAgB,kBACXJ,EAAQ,QAAQ,IAAI,cAAc,GACnCA,EAAQ,QAAQ,IAAI,eAAgB,mCAAmC,EAE3EI,EAAOA,EAAK,SAAS,GAErBA,aAAgB,OAChBA,EAAO,MAAMA,EAAK,MAAM,GAExB,OAAOA,GAAS,WAChBA,EAAO,OAAO,KAAKA,CAAI,GAE3B,MAAMJ,EAAQ,KAAKI,CAAI,CAG3B,CAAC,EAEKH,EAAU,IAAI,QACpB,QAAWK,KAAOP,EAAS,QAAQ,KAAK,EAAG,CACvC,IAAMI,EAAQJ,EAAS,QAAQ,IAAIO,CAAG,EACtC,GAAIH,IAAU,QACV,GAAI,OAAOA,GAAU,SACjBF,EAAQ,IAAIK,EAAKH,CAAK,UACf,MAAM,QAAQA,CAAK,EAC1B,QAAWI,KAAKJ,EACZF,EAAQ,OAAOK,EAAKC,CAAC,EAIrC,CACA,IAAMC,EAAST,EAAS,YAAY,MAC9BK,EAAO,MAAML,EAAS,KAAK,EACjC,OAAO,IAAI,SAASK,EAAM,CAAC,OAAAI,EAAQ,QAAAP,CAAO,CAAC,CAC/C,MACc,CACV,OAAO,SAAS,MAAM,CAC1B,CAEJ,CACJ,EAEMb,GAAN,KAA4D,CAC/CqB,GACTnB,GACAoB,GACAnB,GAAmB,wBAEnB,YAAYoB,EAAqDnB,EAAiCoB,EAAmB,CACjH,GAAI,EAAED,IAAuB,QAAanB,IAAc,QACpD,MAAM,IAAI,MAAM,oEAAoE,EAExF,KAAKF,GAAaE,EAClB,KAAKkB,GAAWE,EAChB,KAAKH,GAAsBE,CAC/B,CAEA,QAAQlB,EAAuB,CAC3B,YAAKF,GAAWE,EACT,IACX,CAEA,gBAAgBD,EAAsC,CAClD,YAAKF,GAAaE,EACX,IACX,CAEA,MAAM,OAA6B,CAC/B,IAAIA,EAAY,KAAKF,GACrB,OAAIE,IAAc,QACV,KAAKiB,KAAwB,SAC7BjB,EAAY,IAAIqB,GAAsB,MAAM,KAAKJ,IAAqB,MAAM,EAAG,KAAKC,EAAQ,GAGpGlB,IAAc,IAAIsB,EAEX,IAAIzB,GAAkBG,EAAW,KAAKD,GAAU,IAAI,CAC/D,CACJ,EAEewB,GAAf,KAAgE,CAC5DL,GACAM,GAA0B,CAAC,EAE3B,cAAcC,EAA8B,CACxC,YAAKD,GAAc,CAAC,GAAI,KAAKA,GAAc,GAAGC,CAAU,EACjD,IACX,CAEA,QAAQL,EAAyB,CAC7B,YAAKF,GAAWE,EACT,IACX,CAEA,iBAAqC,CACjC,IAAMM,EAAU,KAAK,uBAAuB,GAAG,KAAKF,EAAW,EAE/D,OAAO,IAAI5B,GAAyB8B,EAAS,OAAW,KAAKR,EAAQ,CACzE,CAIA,MAAM,OAA6B,CAC/B,OAAO,MAAM,KAAK,gBAAgB,EAAE,MAAM,CAC9C,CACJ,EAEMxB,GAAN,cAAsB6B,EAAuB,CAChCI,GACT,YAAYlC,EAAuB,CAC/B,MAAM,EACN,KAAKkC,GAAOlC,CAChB,CAEA,MAAgB,0BAA0BgC,EAAwB,CAC9D,IAAMG,EAAsB,CACxB,WAAAH,EACA,WAAY,CACR,YAAa,CAAC,uBAAuB,CACzC,EACA,gBAAiB,CACb,UAAW,CAAC,CAChB,EACA,KAAM,CAAC,EACP,WAAY,CAAC,KAAM,MAAM,EACzB,UAAW,CAAC,EACZ,QAAS,IAAII,GACb,QAAS,IAAI,GACjB,EAEA,MAAMC,GAAU,KAAKH,GAAM,CAAC,EAAGC,CAAM,EACrC,IAAMG,EAAU,CAAE,OAAQC,GAAQ,GAAGJ,EAAO,UAAU,CAAE,EACxD,OAAOK,GAAsB,WAAWF,CAAO,CACnD,CACJ,EI9LO,IAAMG,GAAa,CACtB,UAAWC,GACX,aAAcC,EAClB",
6
+ "names": ["isIP", "Cookie", "parseHost", "headers", "defaultHost", "host", "port", "isForwardedSsl", "v", "parseProtocol", "defaultProtocol", "proto", "parseRemoteAddress", "url", "remoteAddress", "AbstractHttpMessage", "#headers", "AbstractHttpRequest", "_AbstractHttpRequest", "#id", "parseCookies", "AbstractHttpResponse", "parseResponseCookies", "responseCookie", "s", "cs", "tc", "cookie", "parsed", "result", "MIMEType", "MIMEType", "WILDCARD_TYPE", "ALL", "APPLICATION_OCTET_STREAM_VALUE", "APPLICATION_OCTET_STREAM", "isWildcardType", "mimeType", "isWildcardSubtype", "isConcrete", "InvalidMimeTypeError", "message", "options", "createMimeType", "type", "subtype", "charset", "input", "result", "error", "getSubtypeSuffix", "suffixIndex", "isCompatibleWith", "a", "b", "aSuffix", "bSuffix", "mimeTypes", "MediaType", "_MediaType", "MIMEType", "APPLICATION_OCTET_STREAM_VALUE", "#PARAM_QUALITY_FACTOR", "input", "#checkToken", "key", "value", "isQuoted", "unquotedValue", "unquote", "q", "InvalidMediaTypeError", "token", "i", "c", "qualityFactor", "mediaTypes", "type", "mediaType", "mimeType", "message", "fileExtensionToMediaTypes", "map", "line", "trimmed", "parts", "extensions", "ext", "existing", "isQuoted", "s", "unquote", "parseHeader", "value", "list", "start", "end", "i", "toList", "values", "MapHttpHeaders", "name", "values", "toList", "value", "prev", "EMPTY_HTTP_HEADERS", "getContentType", "headers", "MediaType", "AbstractClientHttpRequest", "AbstractHttpRequest", "method", "uri", "MapHttpHeaders", "AbstractClientHttpResponse", "AbstractHttpResponse", "statusCode", "headers", "DefaultHttpStatusCode", "#value", "value", "HttpStatus", "_HttpStatus", "#VALUES", "key", "code", "status", "#phrase", "phrase", "httpStatusCode", "FetchClientHttpRequest", "AbstractClientHttpRequest", "#body", "method", "uri", "body", "headers", "key", "value", "toHttpHeaders", "result", "MapHttpHeaders", "FetchClientHttpResponse", "AbstractClientHttpResponse", "#response", "response", "httpStatusCode", "FetchClientHttpConnector", "#fetch", "fetchFn", "requestCallback", "fetchClientHttpRequest", "fetchRequest", "fetchResponse", "stream", "MockClientHttpRequest", "AbstractClientHttpRequest", "#writeHandler", "#body", "uri", "method", "body", "chunks", "reader", "done", "value", "doneReading", "handler", "asyncIterator", "MockClientHttpResponse", "AbstractHttpResponse", "#statusCode", "status", "MapHttpHeaders", "httpStatusCode", "name", "charset", "chunk", "http", "subPath", "container", "start", "end", "elements", "DefaultPathContainer", "slice", "path", "e", "HTTP_OPTIONS", "parsePath", "path", "options", "DefaultPathContainer", "HTTP_OPTIONS", "_DefaultPathContainer", "#SEPARATORS", "#path", "#elements", "elements", "separator", "separatorElement", "start", "end", "i", "segment", "#decodeAndParsePathSegment", "DefaultPathSegment", "paramsIndex", "valueToMatch", "pathParameterContent", "parameters", "#parsePathParameters", "content", "parameter", "#parsePathParameterValue", "values", "input", "output", "eqIndex", "name", "value", "v", "_DefaultPathSegment", "#EMPTY_PARAMS", "separatorOrValueToMatch", "#value", "#valueToMatch", "#parameters", "parseRequestPath", "uri", "contextPath", "DefaultRequestPath", "_DefaultRequestPath", "#initContextPath", "path", "parsePath", "#validateContextPath", "length", "counter", "i", "element", "subPath", "fullPath", "#extractPathWithinApplication", "contextPathLength", "rawPath", "contextPathContainer", "pathWithinApplication", "#fullPath", "#contextPath", "#pathWithinApplication", "AbstractServerHttpRequest", "AbstractHttpRequest", "#sslInfo", "#path", "ExtendedHttpIncomingMessage", "http", "ExtendedHttpServerResponse", "AbstractServerHttpResponse", "AbstractHttpResponse", "#cookies", "#statusCode", "#state", "#commitActions", "statusCode", "httpStatusCode", "cookie", "action", "state", "body", "buffer", "error", "writeAction", "allActions", "acc", "cur", "_error", "ServerHttpResponseDecorator", "_ServerHttpResponseDecorator", "#delegate", "response", "statusCode", "cookie", "body", "AbstractServerHttpResponse", "DefaultWebExchange", "#attributes", "#logId", "#logPrefix", "request", "response", "codecConfigurer", "LOG_ID_ATTRIBUTE", "name", "value", "GatewayLogging", "getLogger", "name", "isLoggingSuppressed", "hints", "LOG_PREFIX_HINT", "getLogPrefix", "AbstractEncoder", "#encodableMimeTypes", "getLogger", "supportedMimeTypes", "logger", "type", "mimeType", "supportedMimeType", "isCompatibleWith", "BlobEncoder", "ALL", "input", "hints", "part", "isLoggingSuppressed", "#logValue", "prefix", "getLogPrefix", "StringEncoder", "_StringEncoder", "mimeTypes", "logPrefix", "traceEnabled", "createMimeType", "LoggingCodecSupport", "getLogger", "#enableLoggingRequestDetails", "enable", "MultipartHttpMessageReader", "_MultipartHttpMessageReader", "LoggingCodecSupport", "MediaType", "#partReader", "partReader", "type", "mediaType", "#supportsMediaType", "supportedMediaType", "isCompatibleWith", "message", "hints", "stream", "result", "name", "value", "DefaultPartHttpMessageReader", "EncoderHttpMessageWriter", "_EncoderHttpMessageWriter", "#encoder", "#mediaTypes", "#defaultMediaType", "encoder", "MediaType", "mediaType", "isConcrete", "type", "input", "message", "hints", "resolvedMediaType", "#updateContentType", "part", "AbstractEncoder", "getContentType", "fallback", "useFallback", "addDefaultCharsetIfNeeded", "main", "defaultType", "defaultCharset", "result", "BaseDefaultCodecs", "#multipartReader", "#maxInMemorySize", "#enableLoggingRequestDetails", "#registerDefaults", "#writers", "#readers", "reader", "registerDefaults", "partReader", "DefaultPartHttpMessageReader", "MultipartHttpMessageReader", "#getBaseWriters", "writers", "BlobEncoder", "bytes", "enable", "StringEncoder", "codecs", "codec", "#initCodec", "size", "BaseCodecConfigurer", "defaultCodecs", "ServerDefaultCodecsImpl", "DefaultServerCodecConfigurer", "createServerCodecConfigurer", "config_default", "stream", "MockServerHttpRequest", "_MockServerHttpRequest", "AbstractServerHttpRequest", "#url", "#sslInfo", "#body", "url", "method", "MapHttpHeaders", "blob", "asyncIterator", "stream", "body", "text", "chunks", "reader", "done", "value", "readDone", "name", "MockServerHttpResponse", "AbstractServerHttpResponse", "#writeHandler", "bodyStream", "handler", "cookie", "it", "resolved", "HttpHeadResponseDecorator", "ServerHttpResponseDecorator", "stream", "FailureAfterResponseCompletedError", "response", "options", "sink", "result", "_error", "promise", "resolve", "reject", "error", "HttpHandlerConnector", "_HttpHandlerConnector", "#logger", "getLogger", "#httpHandler", "#sslInfo", "httpHandler", "sslInfo", "method", "uri", "requestCallback", "requestWriteSink", "handlerSink", "savedResponse", "mockClientRequest", "MockClientHttpRequest", "mockServerResponse", "MockServerHttpResponse", "responseBody", "mockServerRequest", "responseToUse", "e", "message", "request", "body", "headers", "_cookies", "MockServerHttpRequest", "name", "value", "v", "HttpHeadResponseDecorator", "status", "MockClientHttpResponse", "IOGateway", "log", "getLogger", "regexifyOriginFilters", "originFilters", "block", "IOGateway", "allow", "anyExchange", "_exchange", "match", "EMPTY_OBJECT", "NO_MATCH", "variables", "pattern", "opts", "method", "matcher", "exchange", "request", "path", "upgradeMatcher", "request", "match", "NO_MATCH", "IOGateway", "configure", "app", "config", "routes", "applyCors", "request", "options", "cors", "path", "configurer", "handlers", "handler", "matcher", "pattern", "middleware", "exchange", "next", "match", "variables", "sockets", "factory", "route", "regexifyOriginFilters", "compose", "middleware", "fns", "fn", "ctx", "next", "dispatch", "i", "dispatchedCtx", "nextCalled", "nextResolved", "result", "nextCtx", "AsyncLocalStorage", "AsyncLocalStorage", "isClientDisconnectedError", "error", "code", "message", "checkAndLogClientDisconnectedError", "logger", "WebHandlerDecorator", "#delegate", "delegate", "exchange", "ErrorHandlingWebHandler", "#errorHandlers", "errorHandlers", "completion", "e", "handler", "reason", "error", "DefaultWebFilterChain", "_DefaultWebFilterChain", "#filters", "#handler", "#current", "#chian", "filters", "allFilters", "result", "chain", "current", "#invokeFilter", "filter", "FilteringWebHandler", "#chain", "HttpWebHandlerAdapter", "#logger", "#codecConfigurer", "#enableLoggingRequestDetails", "#delegate", "#storage", "logger", "delegate", "config_default", "configurer", "reader", "LoggingCodecSupport", "request", "response", "DefaultWebExchange", "storage", "headers", "result", "key", "value", "query", "exchange", "trace", "status", "error", "logPrefix", "HttpStatus", "checkAndLogClientDisconnectedError", "callback", "resolve", "reject", "WebHttpHandlerBuilder", "_WebHttpHandlerBuilder", "#webHandler", "#filters", "#exceptionHandlers", "#middleware", "#handlerDecorator", "AsyncLocalStorage", "webHandler", "filters", "consumer", "handlers", "decorator", "previousDecorator", "handler", "getLogger", "decorated", "FilteringWebHandler", "ErrorHandlingWebHandler", "adapter", "adapted", "bindToApp", "app", "AppSpec", "bindToServer", "DefaultTestClientBuilder", "DefaultTestClient", "#connector", "#baseUrl", "connector", "baseUrl", "_builder", "input", "init", "method", "uri", "response", "request", "headers", "name", "value", "body", "formDataEntries", "key", "v", "status", "#httpHandlerBuilder", "#sslInfo", "httpHandlerBuilder", "sslInfo", "HttpHandlerConnector", "FetchClientHttpConnector", "AbstractMockServerSpec", "#middleware", "middleware", "builder", "#app", "routes", "AsyncLocalStorage", "configure", "handler", "compose", "WebHttpHandlerBuilder", "TestClient", "bindToApp", "bindToServer"]
7
7
  }